<?php

declare(strict_types=1);

namespace App\Framework\Design;

use App\Framework\Design\Component\Component;
use App\Framework\Design\Component\ComponentCategory;
use App\Framework\Design\Component\ComponentPattern;
use App\Framework\Design\Component\ComponentRegistry;
use App\Framework\Design\Component\ComponentState;
use App\Framework\Filesystem\ValueObjects\FilePath;

/**
 * Scans CSS files to detect and catalog UI components
 */
final readonly class ComponentScanner
{
    /**
     * @param array<string|FilePath> $cssFiles
     */
    public function scanComponents(array $cssFiles): ComponentRegistry
    {
        $components = [];

        foreach ($cssFiles as $cssFile) {
            if (! $cssFile instanceof FilePath) {
                $cssFile = new FilePath($cssFile);
            }

            if (! $cssFile->exists()) {
                continue;
            }

            $cssContent = file_get_contents($cssFile->toString());
            if ($cssContent === false) {
                continue;
            }

            $fileComponents = $this->extractComponentsFromCss($cssContent, $cssFile->toString());
            $components = array_merge($components, $fileComponents);
        }

        return new ComponentRegistry($components);
    }

    /**
     * @return array<Component>
     */
    private function extractComponentsFromCss(string $cssContent, string $filePath): array
    {
        $components = [];
        $processedComponents = [];

        // Remove comments
        $cleanedContent = preg_replace('/\/\*.*?\*\//s', '', $cssContent);
        $cssContent = $cleanedContent !== null ? $cleanedContent : $cssContent;

        // Find all CSS selectors with improved regex that handles nested braces
        preg_match_all('/([^{}]+)\s*{([^{}]*(?:{[^{}]*}[^{}]*)*)}/s', $cssContent, $matches, PREG_SET_ORDER);

        foreach ($matches as $match) {
            $selectors = $match[1];
            $cssRules = trim($match[2]);

            // Skip empty rules
            if (empty($cssRules)) {
                continue;
            }

            // Clean and split selectors
            $selectorList = array_map('trim', explode(',', $selectors));

            foreach ($selectorList as $selector) {
                // Clean up the selector
                $selector = trim($selector);

                // Skip @rules, :root, and other non-component selectors
                if (strpos($selector, '@') === 0 || $selector === ':root' || empty($selector)) {
                    continue;
                }

                $component = $this->analyzeSelector($selector, $cssRules, $filePath);
                if ($component !== null) {
                    // Avoid duplicates based on component name
                    $key = $component->name . '_' . $component->state->value;
                    if (! isset($processedComponents[$key])) {
                        $components[] = $component;
                        $processedComponents[$key] = true;
                    }
                }
            }
        }

        return $components;
    }

    private function analyzeSelector(string $selector, string $cssRules, string $filePath): ?Component
    {
        // Clean up selector - remove :where, :is wrappers
        $cleanedSelector = preg_replace('/:where\s*\((.*?)\)/', '$1', $selector);
        $selector = $cleanedSelector !== null ? $cleanedSelector : $selector;

        $cleanedSelector = preg_replace('/:is\s*\((.*?)\)/', '$1', $selector);
        $selector = $cleanedSelector !== null ? $cleanedSelector : $selector;

        // Ensure selector is non-empty string
        if (empty($selector)) {
            return null;
        }

        // Skip pseudo-elements and certain pseudo-classes
        if (preg_match('/::/', $selector) || preg_match('/:not\(/', $selector)) {
            return null;
        }

        // Skip complex selectors that are not component-like
        if (preg_match('/^\s*(html|body|main|header|footer|section|article|aside|nav|h1|h2|h3|h4|h5|h6|p|div|span|a|ul|ol|li|img|br|hr)\s*$/i', $selector)) {
            return null;
        }

        // Skip overly complex selectors (more than 3 parts)
        if (substr_count($selector, ' ') > 3) {
            return null;
        }

        // Skip selectors that are clearly not components
        if (preg_match('/^\s*(\*|::before|::after|\[|>|\+|~)/i', $selector)) {
            return null;
        }

        $componentName = null;

        // Extract main class name - improved regex to handle more cases
        if (preg_match('/\.([a-zA-Z][a-zA-Z0-9_-]*)(?:\s|:|$|>|\+|~|\[|,)/', $selector, $matches)) {
            $componentName = $matches[1];

            // Skip utility-only classes
            if (strlen($componentName) <= 2) {
                return null;
            }
        }
        // Also handle element-based components (like button, input) - but be more selective
        elseif (preg_match('/^(button|input|select|textarea|table|form|dialog)(?:\s|:|$|\[)/', $selector, $matches)) {
            $componentName = $matches[1];
        }
        // Handle attribute selectors like input[type="button"]
        elseif (preg_match('/(button|input|select|textarea)\[([^\]]+)\]/', $selector, $matches)) {
            $elementType = $matches[1];
            $attributes = $matches[2];

            // Create a meaningful name based on element and attributes
            if (preg_match('/type\s*=\s*["\']([^"\']+)["\']/', $attributes)) {
                preg_match('/type\s*=\s*["\']([^"\']+)["\']/', $attributes, $typeMatches);
                $componentName = $elementType . '-' . $typeMatches[1];
            } else {
                $componentName = $elementType;
            }
        }

        if ($componentName !== null) {
            // Categorize component
            $category = $this->categorizeComponent($componentName);
            $pattern = $this->detectPattern($componentName);
            $state = $this->extractState($selector);

            return new Component(
                name: $componentName,
                selector: $selector,
                cssRules: $cssRules,
                category: $category,
                pattern: $pattern,
                state: $state,
                filePath: $filePath
            );
        }

        return null;
    }

    private function categorizeComponent(string $className): ComponentCategory
    {
        $lowerName = strtolower($className);

        // Button components
        if (preg_match('/(btn|button)/i', $lowerName)) {
            return ComponentCategory::BUTTON;
        }

        // Navigation components
        if (preg_match('/(nav|menu|breadcrumb|tab|sidebar|aside)/i', $lowerName)) {
            return ComponentCategory::NAVIGATION;
        }

        // Form components
        if (preg_match('/(form|input|select|checkbox|radio|field|autosave|textarea)/i', $lowerName)) {
            return ComponentCategory::FORM;
        }

        // Card components
        if (preg_match('/(card|panel|box|tile)/i', $lowerName)) {
            return ComponentCategory::CARD;
        }

        // Alert/notification components
        if (preg_match('/(alert|notification|message|toast|status|error|warning|success)/i', $lowerName)) {
            return ComponentCategory::FEEDBACK;
        }

        // Layout components
        if (preg_match('/(container|grid|row|col|layout|wrapper|section|main|article)/i', $lowerName)) {
            return ComponentCategory::LAYOUT;
        }

        // Typography components
        if (preg_match('/(heading|title|text|font|headline|paragraph)/i', $lowerName)) {
            return ComponentCategory::TYPOGRAPHY;
        }

        // Additional specific components
        if (preg_match('/(header|footer|lightbox|modal|dialog)/i', $lowerName)) {
            return ComponentCategory::LAYOUT;
        }

        if (preg_match('/(csrf)/i', $lowerName)) {
            return ComponentCategory::FORM;
        }

        // Element-based components
        if (preg_match('/^(table)$/i', $lowerName)) {
            return ComponentCategory::LAYOUT;
        }

        return ComponentCategory::OTHER;
    }

    private function detectPattern(string $className): ComponentPattern
    {
        // BEM pattern (block__element--modifier)
        if (preg_match('/^[a-z][a-z0-9]*(__[a-z][a-z0-9]*)?(-{2}[a-z][a-z0-9]*)?$/', $className)) {
            return ComponentPattern::BEM;
        }

        // Utility pattern (single purpose, often prefixed)
        if (preg_match('/^(m|p|text|bg|border|flex|grid|w|h)-/', $className)) {
            return ComponentPattern::UTILITY;
        }

        // Traditional component pattern
        return ComponentPattern::TRADITIONAL;
    }

    private function extractState(string $selector): ComponentState
    {
        if (strpos($selector, ':hover') !== false) {
            return ComponentState::HOVER;
        }

        if (strpos($selector, ':focus') !== false) {
            return ComponentState::FOCUS;
        }

        if (strpos($selector, ':active') !== false) {
            return ComponentState::ACTIVE;
        }

        if (strpos($selector, ':disabled') !== false) {
            return ComponentState::DISABLED;
        }

        return ComponentState::DEFAULT;
    }
}
