<?php

declare(strict_types=1);

namespace Archive\Archived;

use App\Framework\View\RenderContext;

final readonly class TemplateAnalyzer
{
    private const array DYNAMIC_COMPONENTS = [
        'user-info', 'session-data', 'csrf-token', 'timestamp',
        'user-menu', 'cart', 'notifications', 'live-data'
    ];

    private const array TIME_BASED_PATTERNS = [
        'data-timestamp', 'data-live', 'data-realtime',
        'class="live"', 'class="timestamp"'
    ];

    public function analyzeCacheability(string $template, RenderContext $context): CacheabilityInfo
    {
        $analysis = new CacheabilityInfo();

        try {
            // Einfache String-basierte Analyse für bessere Kompatibilität
            $analysis->hasDynamicComponents = $this->findDynamicComponentsInString($template, $analysis);
            $analysis->hasUserSpecificContent = $this->findUserContentInString($template, $context);
            $analysis->hasFormElements = $this->findFormsInString($template);
            $analysis->hasTimeBasedContent = $this->findTimeBasedContent($template);
            $analysis->hasSessionData = $this->findSessionData($template, $context);

            // Fragment-Analyse hinzufügen
            $this->autoDetectFragments($template, $analysis);

            // Bestimme beste Cache-Strategie
            $analysis->cacheStrategy = $this->determineBestStrategy($analysis);
            $analysis->ttl = $this->calculateOptimalTtl($analysis);
            $analysis->dependencies = $this->identifyDependencies($analysis, $context);

        } catch (\Exception $e) {
            // Bei Fehlern: Konservativ statisches Caching
            $analysis->cacheStrategy = CacheStrategy::STATIC;
            $analysis->ttl = 300;
        }

        return $analysis;
    }

    private function findDynamicComponentsInString(string $template, CacheabilityInfo $analysis): bool
    {
        $hasDynamic = false;
        foreach (self::DYNAMIC_COMPONENTS as $component) {
            if (str_contains($template, $component)) {
                $analysis->dynamicComponents[] = $component;
                $hasDynamic = true;
            }
        }
        return $hasDynamic;
    }

    private function findUserContentInString(string $template, RenderContext $context): bool
    {
        // Suche nach user-spezifischen Patterns
        $userPatterns = ['{{user', '$user', 'data-user', 'class="user-'];

        if (array_any($userPatterns, fn($pattern) => str_contains($template, $pattern))) {
            return true;
        }

        // Prüfe Context-Daten auf User-Informationen
        return isset($context->data['user']) || isset($context->data['session']);
    }

    private function findFormsInString(string $template): bool
    {
        return str_contains($template, '<form') || str_contains($template, 'csrf') || str_contains($template, 'token');
    }

    // Entfernte Methoden werden durch die neuen String-basierten Methoden ersetzt

    private function findTimeBasedContent(string $template): bool
    {
        return array_any(self::TIME_BASED_PATTERNS, fn($pattern) => str_contains($template, $pattern));
    }

    private function findSessionData(string $template, RenderContext $context): bool
    {
        // Prüfe auf Session-bezogene Patterns im Template
        $sessionPatterns = ['session.', '{{session', '$session', 'data-session'];

        if (array_any($sessionPatterns, fn($pattern) => str_contains($template, $pattern))) {
            return true;
        }

        // Prüfe Context auf Session-Daten
        return isset($context->data['session']) || isset($context->data['flash']);
    }

    // Fragment-Analyse vereinfacht entfernt für bessere Stabilität

    private function determineBestStrategy(CacheabilityInfo $analysis): CacheStrategy
    {
        // Vollständig statisch
        if ($analysis->isFullyCacheable()) {
            return CacheStrategy::STATIC;
        }

        // Teilweise cacheable mit Fragmenten
        if ($analysis->shouldUseFragmentCache()) {
            return CacheStrategy::FRAGMENT;
        }

        // Teilweise cacheable ohne Fragmente
        if ($analysis->isPartiallyCacheable()) {
            return CacheStrategy::PARTIAL;
        }

        // Vollständig dynamisch
        return CacheStrategy::DYNAMIC;
    }

    private function calculateOptimalTtl(CacheabilityInfo $analysis): int
    {
        $baseTtl = $analysis->cacheStrategy->getTtl();

        // Reduziere TTL basierend auf Komplexität
        $complexity = $analysis->getCacheComplexity();
        $reduction = min($complexity * 60, $baseTtl * 0.5); // Max 50% Reduktion

        return max(0, $baseTtl - (int)$reduction);
    }

    private function identifyDependencies(CacheabilityInfo $analysis, RenderContext $context): array
    {
        $dependencies = [];

        // Template-File als Basis-Dependency
        $dependencies['template'] = $context->template;

        // Dynamic Fragment Dependencies - verwende dynamicFragments anstatt dynamicComponents
        foreach ($analysis->dynamicFragments as $fragment) {
            // Verwende einfach den Fragment-Namen und aktuellen Timestamp
            $dependencies['fragment:' . $fragment] = time();
        }

        // User-spezifische Dependencies
        if ($analysis->hasUserSpecificContent && isset($context->data['user']['id'])) {
            $dependencies['user'] = $context->data['user']['id'];
        }

        return $dependencies;
    }

    private function autoDetectFragments(string $template, CacheabilityInfo $info): void
    {
        $fragmentsFound = false;

        // Erkenne große statische Blöcke (Navigation, Footer, etc.)
        if (preg_match('/<nav[^>]*>(.*?)<\/nav>/s', $template)) {
            $info->addStaticFragment('navigation');
            $fragmentsFound = true;
        }

        if (preg_match('/<footer[^>]*>(.*?)<\/footer>/s', $template)) {
            $info->addStaticFragment('footer');
            $fragmentsFound = true;
        }

        if (preg_match('/<header[^>]*>(.*?)<\/header>/s', $template)) {
            $info->addStaticFragment('header');
            $fragmentsFound = true;
        }

        // Erkenne HTML-Sektionen
        if (preg_match('/<section[^>]*>(.*?)<\/section>/s', $template)) {
            $info->addStaticFragment('content_section');
            $fragmentsFound = true;
        }

        if (preg_match('/<main[^>]*>(.*?)<\/main>/s', $template)) {
            $info->addStaticFragment('main_content');
            $fragmentsFound = true;
        }

        // Erkenne CSS-Klassen-basierte Bereiche
        if (preg_match('/class=["\'].*sidebar.*["\']/', $template)) {
            $info->addStaticFragment('sidebar');
            $fragmentsFound = true;
        }

        // Erkenne dynamische Bereiche
        if (preg_match('/\{\{\s*flash|errors|session/', $template)) {
            $info->addDynamicFragment('user_messages');
            $fragmentsFound = true;
        }

        // Analysiere Template-Komplexität
        $dynamicMatches = preg_match_all('/\{\{[^}]+}}/', $template);
        $templateLength = strlen($template);

        // Debugging der Fragment-Erkennung
        error_log("TemplateAnalyzer DEBUG: Template length: {$templateLength}, Dynamic matches: {$dynamicMatches}, Fragments found: " . ($fragmentsFound ? 'yes' : 'no'));

        // Wenn weniger als 5 dynamische Platzhalter pro 1_000 Zeichen UND keine anderen Fragmente
        $dynamicDensity = $templateLength > 0 ? ($dynamicMatches / $templateLength) * 1000 : 0;

        error_log("TemplateAnalyzer DEBUG: Dynamic density: {$dynamicDensity}, Has dynamic components: " . ($info->hasDynamicComponents ? 'yes' : 'no'));

        // Immer ein template_main Fragment hinzufügen wenn wenig dynamische Inhalte
        if ($dynamicDensity < 5 || (!$fragmentsFound && !$info->hasDynamicComponents)) {
            $info->addStaticFragment('template_main');
            error_log("TemplateAnalyzer DEBUG: Added template_main fragment (density: {$dynamicDensity})");
        }
    }
}
