<?php

declare(strict_types=1);

namespace App\Framework\Database\QueryOptimization;

use App\Framework\Attributes\Initializer;
use App\Framework\Database\DatabaseManager;
use App\Framework\Database\NPlusOneDetection\MachineLearning\NPlusOneDetectionEngine;
use App\Framework\Database\Profiling\ProfilingConnection;
use App\Framework\Database\QueryOptimization\Analysis\EagerLoadingAnalyzer;
use App\Framework\Database\QueryOptimization\Analysis\NPlusOneDetector;
use App\Framework\DI\Container;
use App\Framework\Logging\Logger;
use App\Framework\Logging\ValueObjects\LogContext;

/**
 * Initializer for N+1 Detection Service
 *
 * Sets up the complete N+1 query detection pipeline:
 * 1. QueryLogger for collecting query execution data
 * 2. NPlusOneDetector for analyzing patterns
 * 3. EagerLoadingAnalyzer for generating optimization strategies
 * 4. NPlusOneDetectionEngine (ML-based detection, optional)
 * 5. NPlusOneDetectionService facade
 * 6. Integration with ProfilingConnection for automatic query logging
 */
final readonly class NPlusOneDetectionServiceInitializer
{
    public function __construct(
        private DatabaseManager $databaseManager,
        private Logger $logger
    ) {}

    #[Initializer]
    public function __invoke(Container $container): NPlusOneDetectionService
    {
        // 1. Create QueryLogger
        $queryLogger = new QueryLogger();

        // 2. Create Analysis Components
        $detector = new NPlusOneDetector(
            minExecutionCount: 5,
            minSeverityScore: 4.0
        );

        $eagerLoadingAnalyzer = new EagerLoadingAnalyzer();

        // 3. Get ML Engine (if available)
        $mlEngine = null;
        try {
            if ($container->has(NPlusOneDetectionEngine::class)) {
                $mlEngine = $container->get(NPlusOneDetectionEngine::class);

                if ($mlEngine->isEnabled()) {
                    $this->logger->info('N+1 Detection: ML engine integration enabled', LogContext::withData([
                        'ml_config' => $mlEngine->getConfiguration()
                    ]));
                }
            }
        } catch (\Throwable $e) {
            $this->logger->warning('N+1 Detection: ML engine not available', LogContext::withData([
                'reason' => $e->getMessage()
            ]));
        }

        // 4. Create Detection Service
        $detectionService = new NPlusOneDetectionService(
            queryLogger: $queryLogger,
            detector: $detector,
            eagerLoadingAnalyzer: $eagerLoadingAnalyzer,
            logger: $this->logger,
            mlEngine: $mlEngine
        );

        // 5. Set up integration with ProfilingConnection
        $this->setupProfilingIntegration($queryLogger);

        // 6. Register as singleton
        $container->singleton(NPlusOneDetectionService::class, $detectionService);
        $container->singleton(QueryLogger::class, $queryLogger);

        return $detectionService;
    }

    /**
     * Set up integration between ProfilingConnection and QueryLogger
     */
    private function setupProfilingIntegration(QueryLogger $queryLogger): void
    {
        $connection = $this->databaseManager->getConnection();

        // If connection is a ProfilingConnection, attach QueryLogger
        if ($connection instanceof ProfilingConnection) {
            $integration = new NPlusOneQueryLoggerIntegration($queryLogger);
            $integration->attachToConnection($connection);

            $this->logger->info('N+1 Detection: Integrated with ProfilingConnection');
        }
    }
}
