<?php

declare(strict_types=1);

namespace App\Framework\Design\Analyzer;

use App\Framework\Design\Parser\CssParser;
use App\Framework\Design\ValueObjects\CssParseResult;
use App\Framework\Filesystem\ValueObjects\FilePath;

/**
 * Haupt-Analyzer für das Design System
 */
final readonly class DesignSystemAnalyzer
{
    public function __construct(
        private CssParser $cssParser = new CssParser(),
        private TokenAnalyzer $tokenAnalyzer = new TokenAnalyzer(),
        private ComponentDetector $componentDetector = new ComponentDetector(),
        private ConventionChecker $conventionChecker = new ConventionChecker(),
        private ColorAnalyzer $colorAnalyzer = new ColorAnalyzer()
    ) {
    }

    /**
     * Analysiert ein komplettes Design System
     */
    public function analyzeDesignSystem(string|array $cssFiles): DesignSystemAnalysis
    {
        $files = is_array($cssFiles) ? $cssFiles : [$cssFiles];
        $parseResults = [];

        // Parse alle CSS-Dateien
        foreach ($files as $file) {
            $filePath = $file instanceof FilePath ? $file : FilePath::create($file);
            $parseResults[] = $this->cssParser->parseFile($filePath);
        }

        // Kombiniere alle Ergebnisse
        $combinedResult = $this->combineParseResults($parseResults);

        // Durchführung der verschiedenen Analysen
        $tokenAnalysis = $this->tokenAnalyzer->analyze($combinedResult);
        $componentAnalysis = $this->componentDetector->detectComponents($combinedResult);
        $conventionAnalysis = $this->conventionChecker->checkConventions($combinedResult);
        $colorAnalysis = $this->colorAnalyzer->analyzeColors($combinedResult);

        return new DesignSystemAnalysis(
            sourceFiles: array_map(fn ($result) => $result->sourceFile, $parseResults),
            parseResults: $parseResults,
            combinedResult: $combinedResult,
            tokenAnalysis: $tokenAnalysis,
            componentAnalysis: $componentAnalysis,
            conventionAnalysis: $conventionAnalysis,
            colorAnalysis: $colorAnalysis,
            overallStatistics: $this->calculateOverallStatistics($parseResults)
        );
    }

    /**
     * Analysiert ein einzelnes CSS-Verzeichnis
     */
    public function analyzeDirectory(string $directory, bool $recursive = true): DesignSystemAnalysis
    {
        $parseResults = $this->cssParser->parseDirectory($directory, $recursive);

        if (empty($parseResults)) {
            throw new \InvalidArgumentException("No CSS files found in directory: $directory");
        }

        $combinedResult = $this->combineParseResults($parseResults);

        return new DesignSystemAnalysis(
            sourceFiles: array_map(fn ($result) => $result->sourceFile, $parseResults),
            parseResults: $parseResults,
            combinedResult: $combinedResult,
            tokenAnalysis: $this->tokenAnalyzer->analyze($combinedResult),
            componentAnalysis: $this->componentDetector->detectComponents($combinedResult),
            conventionAnalysis: $this->conventionChecker->checkConventions($combinedResult),
            colorAnalysis: $this->colorAnalyzer->analyzeColors($combinedResult),
            overallStatistics: $this->calculateOverallStatistics($parseResults)
        );
    }

    /**
     * Schnelle Analyse nur für Statistiken
     */
    public function quickAnalyze(string|array $cssFiles): array
    {
        $files = is_array($cssFiles) ? $cssFiles : [$cssFiles];
        $statistics = [];

        foreach ($files as $file) {
            $filePath = $file instanceof FilePath ? $file : FilePath::create($file);
            $result = $this->cssParser->parseFile($filePath);
            $statistics[] = $result->getStatistics();
        }

        return $statistics;
    }

    /**
     * Kombiniert mehrere Parse-Ergebnisse zu einem Gesamt-Ergebnis
     */
    private function combineParseResults(array $parseResults): CssParseResult
    {
        if (empty($parseResults)) {
            throw new \InvalidArgumentException('No parse results to combine');
        }

        if (count($parseResults) === 1) {
            return $parseResults[0];
        }

        $allRules = [];
        $allCustomProperties = [];
        $allClassNames = [];
        $combinedContent = '';

        foreach ($parseResults as $result) {
            $allRules = array_merge($allRules, $result->rules);
            $allCustomProperties = array_merge($allCustomProperties, $result->customProperties);
            $allClassNames = array_merge($allClassNames, $result->classNames);
            $combinedContent .= $result->rawContent . "\n";
        }

        return new CssParseResult(
            sourceFile: null, // Combined result has no single source
            rules: $allRules,
            customProperties: $allCustomProperties,
            classNames: $allClassNames,
            rawContent: $combinedContent
        );
    }

    /**
     * Berechnet Gesamt-Statistiken für alle Dateien
     */
    private function calculateOverallStatistics(array $parseResults): array
    {
        $totalStats = [
            'total_files' => count($parseResults),
            'total_rules' => 0,
            'total_selectors' => 0,
            'total_properties' => 0,
            'total_design_tokens' => 0,
            'total_class_names' => 0,
            'total_content_size' => 0,
            'file_breakdown' => [],
        ];

        foreach ($parseResults as $result) {
            $stats = $result->getStatistics();

            $totalStats['total_rules'] += $stats['total_rules'];
            $totalStats['total_selectors'] += $stats['total_selectors'];
            $totalStats['total_properties'] += $stats['total_properties'];
            $totalStats['total_design_tokens'] += $stats['design_tokens'];
            $totalStats['total_class_names'] += $stats['class_names'];
            $totalStats['total_content_size'] += $stats['content_size_bytes'];

            $totalStats['file_breakdown'][] = $stats;
        }

        // Durchschnittliche Werte berechnen
        $fileCount = max(1, count($parseResults));
        $totalStats['avg_rules_per_file'] = round($totalStats['total_rules'] / $fileCount, 2);
        $totalStats['avg_properties_per_file'] = round($totalStats['total_properties'] / $fileCount, 2);
        $totalStats['avg_tokens_per_file'] = round($totalStats['total_design_tokens'] / $fileCount, 2);
        $totalStats['avg_classes_per_file'] = round($totalStats['total_class_names'] / $fileCount, 2);

        return $totalStats;
    }
}
