<?php

declare(strict_types=1);

namespace App\Framework\Discovery\Enhanced;

use App\Framework\Cache\Cache;
use App\Framework\Discovery\Enhanced\Analysis\DependencyGraphAnalyzer;
use App\Framework\Discovery\Enhanced\Analysis\PerformanceProfileAnalyzer;
use App\Framework\Discovery\Enhanced\Optimization\DiscoveryOptimizer;
use App\Framework\Discovery\Enhanced\Patterns\PatternRecognitionEngine;
use App\Framework\Discovery\Enhanced\Prediction\DiscoveryPredictor;
use App\Framework\Discovery\Enhanced\ValueObjects\DiscoveryMetrics;
use App\Framework\Discovery\Enhanced\ValueObjects\DiscoveryPlan;
use App\Framework\Discovery\Results\DiscoveryRegistry;
use App\Framework\Discovery\UnifiedDiscoveryService;
use App\Framework\Mcp\Core\Services\IntelligentMcpCacheManager;
use App\Framework\Mcp\Core\Services\McpPerformanceMonitor;
use App\Framework\Mcp\Core\ValueObjects\CacheStrategy;

/**
 * Enhanced Auto-Discovery Service with MCP Integration
 *
 * Advanced discovery system that leverages:
 * - MCP caching for intelligent result storage
 * - Performance monitoring for optimization
 * - Pattern recognition for component classification
 * - Predictive discovery for proactive component loading
 * - Dependency graph analysis for better understanding
 */
final readonly class IntelligentDiscoveryService
{
    private IntelligentMcpCacheManager $cacheManager;

    private McpPerformanceMonitor $performanceMonitor;

    private DependencyGraphAnalyzer $dependencyAnalyzer;

    private PerformanceProfileAnalyzer $profileAnalyzer;

    private PatternRecognitionEngine $patternEngine;

    private DiscoveryOptimizer $optimizer;

    private DiscoveryPredictor $predictor;

    public function __construct(
        private UnifiedDiscoveryService $baseDiscoveryService,
        private Cache $cache,
        private array $configuration = []
    ) {
        $this->initializeEnhancedComponents();
    }

    /**
     * Enhanced discovery with intelligent caching and optimization
     */
    public function discover(
        array $paths = [],
        array $attributes = [],
        ?DiscoveryPlan $plan = null
    ): DiscoveryResult {
        return $this->performanceMonitor->monitor(
            'intelligent_discovery',
            'discover',
            function () use ($paths, $attributes, $plan) {
                return $this->executeEnhancedDiscovery($paths, $attributes, $plan);
            },
            [
                'paths_count' => count($paths),
                'attributes_count' => count($attributes),
                'has_plan' => $plan !== null,
            ]
        );
    }

    /**
     * Discover components with predictive loading
     */
    public function discoverWithPrediction(array $paths = []): DiscoveryResult
    {
        // Get prediction of what components will be needed
        $predictions = $this->predictor->predictRequiredComponents($paths);

        // Create optimized discovery plan
        $plan = $this->optimizer->createOptimalPlan($paths, $predictions);

        return $this->discover($paths, [], $plan);
    }

    /**
     * Analyze component dependencies and create dependency graph
     */
    public function analyzeDependencies(array $components = []): DependencyGraph
    {
        return $this->cacheManager->remember(
            'dependency_analyzer',
            'analyze_dependencies',
            ['components' => md5(serialize($components))],
            fn () => $this->dependencyAnalyzer->analyze($components),
            CacheStrategy::LONG
        );
    }

    /**
     * Get component performance profiles
     */
    public function getComponentProfiles(array $componentNames = []): array
    {
        return $this->cacheManager->remember(
            'profile_analyzer',
            'get_component_profiles',
            ['components' => md5(serialize($componentNames))],
            fn () => $this->profileAnalyzer->analyzeComponents($componentNames),
            CacheStrategy::MEDIUM
        );
    }

    /**
     * Recognize patterns in discovered components
     */
    public function recognizePatterns(DiscoveryRegistry $registry): PatternAnalysisResult
    {
        return $this->patternEngine->recognizePatterns($registry);
    }

    /**
     * Optimize discovery process based on historical data
     */
    public function optimizeDiscovery(array $historicalMetrics): OptimizationResult
    {
        return $this->optimizer->optimize($historicalMetrics);
    }

    /**
     * Get enhanced discovery metrics
     */
    public function getDiscoveryMetrics(): DiscoveryMetrics
    {
        $cacheMetrics = $this->cacheManager->getMetrics();
        $performanceMetrics = $this->performanceMonitor->getAggregatedMetrics('intelligent_discovery');

        return new DiscoveryMetrics(
            cacheHitRate: $cacheMetrics->hitRate,
            averageDiscoveryTime: $performanceMetrics->averageExecutionTime,
            componentsDiscovered: $this->getDiscoveredComponentsCount(),
            patternMatchRate: $this->patternEngine->getMatchRate(),
            predictionAccuracy: $this->predictor->getAccuracy(),
            memoryEfficiency: $this->calculateMemoryEfficiency(),
            optimizationImpact: $this->optimizer->getOptimizationImpact()
        );
    }

    /**
     * Clear enhanced discovery caches
     */
    public function clearEnhancedCaches(): void
    {
        $this->cacheManager->invalidateTool('intelligent_discovery');
        $this->cacheManager->invalidateTool('dependency_analyzer');
        $this->cacheManager->invalidateTool('profile_analyzer');
        $this->patternEngine->clearPatternCache();
        $this->predictor->clearPredictionCache();
    }

    /**
     * Execute enhanced discovery with all optimizations
     */
    private function executeEnhancedDiscovery(
        array $paths,
        array $attributes,
        ?DiscoveryPlan $plan
    ): DiscoveryResult {
        // Use plan or create default optimization strategy
        $actualPlan = $plan ?? $this->optimizer->createDefaultPlan($paths, $attributes);

        // Execute base discovery with optimizations
        $baseResult = $this->executeOptimizedDiscovery($actualPlan);

        // Enhance results with pattern recognition
        $patterns = $this->recognizePatterns($baseResult->getRegistry());

        // Analyze dependencies
        $dependencies = $this->analyzeDependencies($baseResult->getComponents());

        // Create enhanced result
        return new DiscoveryResult(
            registry: $baseResult->getRegistry(),
            patterns: $patterns,
            dependencies: $dependencies,
            metrics: $this->getDiscoveryMetrics(),
            plan: $actualPlan
        );
    }

    /**
     * Execute discovery with optimization strategies
     */
    private function executeOptimizedDiscovery(DiscoveryPlan $plan): BaseDiscoveryResult
    {
        // Apply memory optimization
        $this->optimizer->applyMemoryOptimizations();

        // Execute with performance monitoring
        return $this->performanceMonitor->monitor(
            'base_discovery',
            'execute_optimized',
            function () use ($plan) {
                // Use base discovery service with plan optimizations
                return $this->baseDiscoveryService->discover(
                    $plan->getPaths(),
                    $plan->getAttributes(),
                    $plan->getDiscoveryContext()
                );
            },
            $plan->getMetadata()
        );
    }

    /**
     * Initialize enhanced discovery components
     */
    private function initializeEnhancedComponents(): void
    {
        // Initialize MCP-integrated cache manager
        $this->cacheManager = new IntelligentMcpCacheManager($this->cache, [
            'discovery_cache' => [
                'default_ttl' => 3600,
                'compression_threshold' => 100 * 1024, // 100KB
                'max_memory_usage' => 50 * 1024 * 1024, // 50MB
            ],
        ]);

        // Initialize performance monitor
        $this->performanceMonitor = new McpPerformanceMonitor($this->cache);

        // Initialize analysis components
        $this->dependencyAnalyzer = new DependencyGraphAnalyzer($this->cacheManager);
        $this->profileAnalyzer = new PerformanceProfileAnalyzer($this->performanceMonitor);
        $this->patternEngine = new PatternRecognitionEngine($this->cacheManager);
        $this->optimizer = new DiscoveryOptimizer($this->performanceMonitor);
        $this->predictor = new DiscoveryPredictor($this->cacheManager, $this->patternEngine);
    }

    /**
     * Get count of discovered components
     */
    private function getDiscoveredComponentsCount(): int
    {
        return $this->cacheManager->remember(
            'discovery_stats',
            'component_count',
            [],
            function () {
                // Count components from base discovery service
                // This would integrate with the actual discovery registry
                return 0; // Placeholder
            },
            CacheStrategy::SHORT
        );
    }

    /**
     * Calculate memory efficiency metrics
     */
    private function calculateMemoryEfficiency(): float
    {
        $metrics = $this->cacheManager->getMetrics();

        // Calculate efficiency based on cache compression ratio and memory usage
        $compressionRatio = $metrics->compressionRatio;
        $memoryUsage = $metrics->memoryUsage;

        // Efficiency score: better compression + lower memory = higher efficiency
        return min(1.0, $compressionRatio * 0.7 + (1.0 - min(1.0, $memoryUsage / (50 * 1024 * 1024))) * 0.3);
    }
}
