<?php

declare(strict_types=1);

namespace App\Framework\Core;

use App\Framework\Auth\AuthMapper;
use App\Framework\CommandBus\CommandHandlerCompiler;
use App\Framework\CommandBus\CommandHandlerMapper;
use App\Framework\Config\Configuration;
use App\Framework\Console\ConsoleCommandMapper;
use App\Framework\DI\AttributeProcessorRegistry;
use App\Framework\DI\DefaultContainer;
use App\Framework\DI\InitializerMapper;
use App\Framework\QueryBus\QueryHandlerCompiler;
use App\Framework\QueryBus\QueryHandlerMapper;
use Archive\Async1\DiscoveryFactory;

/**
 * Verwaltet die Entdeckung und Verarbeitung von Attributen
 */
readonly class AttributeDiscoveryService
{
    public function __construct(
        private DefaultContainer $container,
        private PathProvider     $pathProvider,
        private Configuration    $config
    ) {}

    /**
     * Führt die Attribut-Discovery durch und verarbeitet die gefundenen Attribute
     */
    public function discoverAndProcess(): array
    {
        $useAsyncDiscovery = $this->config->get('async_discovery', true);
        $srcDir = $this->pathProvider->getSourcePath();

        // Discovery erstellen
        $discoveryFactory = new DiscoveryFactory();
        $discovery = $discoveryFactory->create($useAsyncDiscovery, $srcDir);

        // Attribute-Processor-Registry initialisieren
        $processorRegistry = $this->createProcessorRegistry();

        // Attribute entdecken
        $results = $discovery->discover($srcDir);

        // Alle Attribute verarbeiten
        return $processorRegistry->processAll($results);
    }

    /**
     * Erstellt und konfiguriert die AttributeProcessorRegistry
     */
    private function createProcessorRegistry(): AttributeProcessorRegistry
    {
        $processorRegistry = new AttributeProcessorRegistry($this->container);

        // Mapper registrieren
        $this->registerMappers($processorRegistry);

        // Compiler registrieren
        $this->registerCompilers($processorRegistry);

        return $processorRegistry;
    }

    /**
     * Registriert alle AttributeMapper
     */
    private function registerMappers(AttributeProcessorRegistry $registry): void
    {
        $registry
            ->registerMapper(RouteMapper::class)
            ->registerMapper(CommandHandlerMapper::class)
            ->registerMapper(\App\Framework\Core\Events\EventHandlerMapper::class)
            ->registerMapper(\App\Framework\EventBus\EventHandlerMapper::class)
            ->registerMapper(QueryHandlerMapper::class)
            ->registerMapper(ConsoleCommandMapper::class)
            ->registerMapper(AuthMapper::class)

            ->registerMapper(InitializerMapper::class);

        // Hier können weitere Mapper registriert werden
    }

    /**
     * Registriert alle AttributeCompiler
     */
    private function registerCompilers(AttributeProcessorRegistry $registry): void
    {
        $registry
            ->registerCompiler(RouteCompiler::class)
            ->registerCompiler(CommandHandlerCompiler::class)
            ->registerCompiler(\App\Framework\Core\Events\EventHandlerCompiler::class)
            ->registerCompiler(\App\Framework\EventBus\EventHandlerCompiler::class)
            ->registerCompiler(QueryHandlerCompiler::class);

        // Hier können weitere Compiler registriert werden
    }
}
