<?php

declare(strict_types=1);

namespace App\Application\Admin\Development;

use App\Application\Admin\Service\AdminLayoutProcessor;
use App\Framework\Attributes\Route;
use App\Framework\DateTime\Clock;
use App\Framework\Design\Component\ComponentCategory;
use App\Framework\Design\ComponentScanner;
use App\Framework\Design\Service\DesignSystemAnalyzer;
use App\Framework\Filesystem\ValueObjects\FilePath;
use App\Framework\Filesystem\FileScanner;
use App\Framework\Filesystem\ValueObjects\FilePattern;
use App\Framework\Http\HttpRequest;
use App\Framework\Http\Method;
use App\Framework\Http\Status;
use App\Framework\Meta\MetaData;
use App\Framework\Router\Result\JsonResult;
use App\Framework\Router\Result\ViewResult;

/**
 * Design System Documentation Controller
 */
final readonly class DesignSystemController
{
    public function __construct(
        private DesignSystemAnalyzer $analyzer,
        private FileScanner $fileScanner,
        private ComponentScanner $componentScanner,
        private AdminLayoutProcessor $layoutProcessor,
        private Clock $clock,
    ) {
    }

    #[Route(path: '/admin/dev/design-system', method: Method::GET, name: 'admin.dev.design-system')]
    public function dashboard(HttpRequest $request): ViewResult
    {
        // Analysiere CSS Dateien
        $cssFiles = $this->findCssFiles();
        $analysis = $this->analyzer->analyze($cssFiles);

        $data = [
            'title' => 'Design System Dashboard',
            'analysis' => $analysis,
            'maturity_level' => $analysis->getMaturityLevel(),
            'overall_score' => $analysis->getOverallDesignSystemScore(),
            'critical_issues' => $analysis->getCriticalIssues(),
            'quick_wins' => $analysis->getQuickWins(),
            'current_year' => $this->clock->now()->format('Y'),
        ];

        $finalData = $this->layoutProcessor->processLayoutFromArray($data);

        return new ViewResult(
            'design-dashboard',
            new MetaData('Design System Dashboard', 'Design System Dashboard'),
            $finalData
        );
    }

    #[Route(path: '/design-system/tokens', method: Method::GET)]
    public function tokens(HttpRequest $request): ViewResult
    {
        $cssFiles = $this->findCssFiles();
        $analysis = $this->analyzer->analyze($cssFiles);

        // Gruppiere Tokens nach Typ
        $tokensByType = [];
        foreach ($analysis->tokenAnalysis->usedTokens as $token) {
            $type = $token->getType()->value;
            if (! isset($tokensByType[$type])) {
                $tokensByType[$type] = [];
            }
            $tokensByType[$type][] = $token;
        }

        return new ViewResult(
            'tokens',
            new MetaData('Design System Tokens', 'Design System Tokens'),
            [
            'analysis' => $analysis->tokenAnalysis,
            'tokens_by_type' => $tokensByType,
            'coverage' => $analysis->tokenAnalysis->getTokenCoverage(),
            'missing_tokens' => $analysis->tokenAnalysis->missingTokens,
            'unused_tokens' => $analysis->tokenAnalysis->unusedTokens,
        ]
        );
    }

    #[Route(path: '/design-system/colors', method: Method::GET)]
    public function colors(HttpRequest $request): ViewResult
    {
        $cssFiles = $this->findCssFiles();
        $analysis = $this->analyzer->analyze($cssFiles);

        return new ViewResult(
            'colors',
            new Metadata('Design System Colors', 'Design System Colors'),
            [
            'analysis' => $analysis->colorAnalysis,
            'palette_summary' => $analysis->colorAnalysis->getPaletteSummary(),
            'contrast_issues' => $analysis->colorAnalysis->getWorstContrastPairs(),
            'duplicates' => $analysis->colorAnalysis->duplicateColors,
            'format_recommendations' => $analysis->colorAnalysis->getFormatRecommendations(),
        ]
        );
    }

    #[Route(path: '/design-system/components', method: Method::GET)]
    public function components(HttpRequest $request): ViewResult
    {
        $cssFiles = $this->findCssFiles();
        $componentRegistry = $this->componentScanner->scanComponents($cssFiles);

        // Get search query if provided
        $search = $request->query->get('search', '');
        $category = $request->query->get('category', '');

        $components = $componentRegistry->getAllComponents();

        // Filter by search
        if (! empty($search)) {
            $components = $componentRegistry->searchComponents($search);
        }

        // Filter by category
        if (! empty($category)) {
            $categoryEnum = ComponentCategory::tryFrom($category);
            if ($categoryEnum !== null) {
                $components = $componentRegistry->getByCategory($categoryEnum);
            }
        }

        // Transform components for template
        $templateComponents = [];
        foreach ($components as $component) {
            $templateComponents[] = [
                'name' => $component->name,
                'displayName' => $component->getDisplayName(),
                'category' => $component->category->value,
                'pattern' => strtoupper($component->pattern->value),
                'previewHtml' => $component->getPreviewHtml(),
                'selector' => $component->selector,
            ];
        }

        return new ViewResult(
            'components-overview',
            new Metadata('Design System Components', 'Design System Components'),
            [
                'components' => $templateComponents,
                'componentRegistry' => $componentRegistry,
                'categoryCounts' => $componentRegistry->getCategoryCounts(),
                'patternCounts' => $componentRegistry->getPatternCounts(),
                'totalComponents' => $componentRegistry->getTotalComponents(),
                'groupedComponents' => $componentRegistry->groupByCategory(),
                'searchQuery' => $search,
                'selectedCategory' => $category,
                'categories' => ComponentCategory::cases(),
            ]
        );
    }

    #[Route(path: '/design-system/components/{componentName}', method: Method::GET)]
    public function componentDetail(HttpRequest $request, ?string $componentName = null): ViewResult
    {
        // If componentName wasn't injected by route parameter, extract from path
        if ($componentName === null) {
            $pathParts = explode('/', trim($request->path, '/'));
            $componentName = end($pathParts) ?: '';
        }

        $cssFiles = $this->findCssFiles();
        $componentRegistry = $this->componentScanner->scanComponents($cssFiles);

        $component = $componentRegistry->findByName($componentName);

        if ($component === null) {
            return new ViewResult(
                'component-not-found',
                new Metadata('Component Not Found', 'Component Not Found'),
                ['componentName' => $componentName]
            );
        }

        // Get all variants of this component
        $variants = $componentRegistry->getComponentVariants($componentName);

        return new ViewResult(
            'component-detail',
            new Metadata("Component: {$component->getDisplayName()}", "Component: {$component->getDisplayName()}"),
            [
                'component' => $component,
                'variants' => $variants,
                'allComponents' => $componentRegistry->getAllComponents(),
            ]
        );
    }

    #[Route(path: '/design-system/conventions', method: Method::GET)]
    public function conventions(HttpRequest $request): ViewResult
    {
        $cssFiles = $this->findCssFiles();
        $analysis = $this->analyzer->analyze($cssFiles);

        return new ViewResult(
            'conventions',
            new Metadata('Design System Conventions', 'Design System Conventions'),
            [
            'analysis' => $analysis->conventionAnalysis,
            'violations_by_severity' => $analysis->conventionAnalysis->getViolationsBySeverity(),
            'worst_areas' => $analysis->conventionAnalysis->getWorstAreas(),
            'best_areas' => $analysis->conventionAnalysis->getBestAreas(),
            'improvement_potential' => $analysis->conventionAnalysis->getImprovementPotential(),
        ]
        );
    }

    #[Route(path: '/design-system/roadmap', method: Method::GET)]
    public function roadmap(HttpRequest $request): ViewResult
    {
        $cssFiles = $this->findCssFiles();
        $analysis = $this->analyzer->analyze($cssFiles);

        return new ViewResult(
            'roadmap',
            new Metadata('Design System Roadmap', 'Design System Roadmap'),
            [
            'roadmap' => $analysis->getDevelopmentRoadmap(),
            'critical_issues' => $analysis->getCriticalIssues(),
            'quick_wins' => $analysis->getQuickWins(),
            'current_score' => $analysis->getOverallDesignSystemScore(),
            'maturity_level' => $analysis->getMaturityLevel(),
        ]
        );
    }

    #[Route(path: '/api/design-system/export', method: Method::GET)]
    public function export(HttpRequest $request): JsonResult
    {
        $cssFiles = $this->findCssFiles();
        $analysis = $this->analyzer->analyze($cssFiles);

        $format = $request->query->get('format', 'json');

        return match($format) {
            'summary' => new JsonResult([
                'overall_score' => $analysis->getOverallDesignSystemScore(),
                'maturity_level' => $analysis->getMaturityLevel(),
                'critical_issues_count' => count($analysis->getCriticalIssues()),
                'quick_wins_count' => count($analysis->getQuickWins()),
                'token_coverage' => $analysis->tokenAnalysis->getTokenCoverage()['usage_percentage'],
                'color_consistency' => $analysis->colorAnalysis->getConsistencyScore(),
                'convention_score' => $analysis->conventionAnalysis->overallScore,
            ]),
            'full' => new JsonResult($analysis->exportReport()),
            default => new JsonResult($analysis->exportReport())
        };
    }

    #[Route(path: '/api/design-system/analyze', method: Method::POST)]
    public function analyzeFiles(HttpRequest $request): JsonResult
    {
        $files = $request->parsedBody->get('files', []);

        if (empty($files)) {
            return new JsonResult(['error' => 'No files provided'], Status::BAD_REQUEST);
        }

        $cssFiles = array_map(fn ($file) => new FilePath($file), $files);

        try {
            $analysis = $this->analyzer->analyze($cssFiles);

            return new JsonResult([
                'success' => true,
                'analysis' => [
                    'overall_score' => $analysis->getOverallDesignSystemScore(),
                    'maturity_level' => $analysis->getMaturityLevel(),
                    'summary' => [
                        'total_tokens' => $analysis->tokenAnalysis->totalTokens,
                        'total_colors' => $analysis->colorAnalysis->totalColors,
                        'total_components' => $analysis->componentAnalysis->totalComponents,
                        'convention_score' => $analysis->conventionAnalysis->overallScore,
                    ],
                    'critical_issues' => $analysis->getCriticalIssues(),
                    'quick_wins' => $analysis->getQuickWins(),
                ],
            ]);
        } catch (\Exception $e) {
            return new JsonResult([
                'success' => false,
                'error' => $e->getMessage(),
            ], Status::INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * Findet alle CSS-Dateien im Projekt über FileScanner
     * @return array<int, FilePath>
     */
    private function findCssFiles(): array
    {
        $cssFiles = [];
        $cssPattern = FilePattern::css();

        // CSS Dateien in resources/css/
        $resourcesPath = new FilePath(__DIR__ . '/../../../../resources/css');
        if ($resourcesPath->exists() && $resourcesPath->isDirectory()) {
            $collection = $this->fileScanner->findFiles($resourcesPath, $cssPattern);
            foreach ($collection as $file) {
                $cssFiles[] = $file->getPath();
            }
        }

        // CSS Dateien in public/assets/
        $publicPath = new FilePath(__DIR__ . '/../../../../public/assets');
        if ($publicPath->exists() && $publicPath->isDirectory()) {
            $collection = $this->fileScanner->findFiles($publicPath, $cssPattern);
            foreach ($collection as $file) {
                $cssFiles[] = $file->getPath();
            }
        }

        return $cssFiles;
    }
}
