<?php

namespace App\Framework\View\Caching\Analysis;

use App\Framework\View\Loading\TemplateLoader;

final readonly class SmartTemplateAnalyzer implements TemplateAnalyzer
{
    public function __construct(
        private TemplateLoader $loader,
    ) {}

    public function analyze(string $template): TemplateAnalysis
    {
        try {
            $content = $this->loader->load($template);
        } catch (\Throwable $e) {
            return $this->createFallbackAnalysis($template);
        }

        $dependencies = $this->getDependencies($template);
        $cacheability = $this->getCacheability($template);
        $fragments = $this->findFragments($content);

        $strategy = $this->determineOptimalStrategy($template, $cacheability, $dependencies);
        $ttl = $this->calculateOptimalTtl($strategy, $cacheability);

        return new TemplateAnalysis($template, $strategy, $ttl, $dependencies, $cacheability, $fragments);
    }

    public function getDependencies(string $template): array
    {
        try {
            $content = $this->loader->load($template);
            $dependencies = [];

            // Finde @include directives
            if (preg_match_all('/@include\s*\([\'"](.+?)[\'"]\)/', $content, $matches)) {
                $dependencies['includes'] = $matches[1];
            }

            // Finde <component> tags
            if (preg_match_all('/<component[^>]*name=[\'"]([^\'"]+)[\'"]/', $content, $matches)) {
                $dependencies['components'] = $matches[1];
            }

            return $dependencies;
        } catch (\Exception $e) {
            return [];
        }
    }

    public function getCacheability(string $template): CacheabilityScore
    {
        try {
            $content = $this->loader->load($template);
            $score = new CacheabilityScore();

            // Analysiere Content
            $score->hasUserSpecificContent = $this->hasUserContent($content);
            $score->hasCsrfTokens = $this->hasCsrfTokens($content);
            $score->hasTimestamps = $this->hasTimestamps($content);
            $score->hasRandomElements = $this->hasRandomElements($content);
            $score->staticContentRatio = $this->calculateStaticRatio($content);

            return $score;
        } catch (\Exception $e) {
            return new CacheabilityScore();
        }
    }

    private function determineOptimalStrategy(string $template, CacheabilityScore $cacheability, array $dependencies): CacheStrategy
    {
        // Nicht cacheable = NoCache
        if (!$cacheability->isCacheable()) {
            return CacheStrategy::NO_CACHE;
        }

        // Components
        if (str_contains($template, 'component') || str_contains($template, 'partial')) {
            return CacheStrategy::COMPONENT;
        }

        // Layouts und statische Seiten
        if (str_contains($template, 'layout') || $cacheability->staticContentRatio > 0.8) {
            return CacheStrategy::FULL_PAGE;
        }

        // Default: Fragment
        return CacheStrategy::FRAGMENT;
    }

    private function calculateOptimalTtl(CacheStrategy $strategy, CacheabilityScore $cacheability): int
    {
        $baseTtl = match($strategy) {
            CacheStrategy::FULL_PAGE => 1800,
            CacheStrategy::COMPONENT => 900,
            CacheStrategy::FRAGMENT => 300,
            default => 0
        };

        // TTL basierend auf Cacheability Score anpassen
        return (int) ($baseTtl * $cacheability->getScore());
    }

    private function findFragments(string $content)
    {
        // Vereinfachte Fragment-Erkennung
        $fragments = [];

        // Finde große statische HTML-Blöcke
        if (preg_match_all('/<(?:nav|header|footer|aside)[^>]*>(.*?)<\/(?:nav|header|footer|aside)>/s', $content, $matches)) {
            foreach ($matches[0] as $i => $match) {
                if (strlen($match) > 200 && !str_contains($match, '{{')) {
                    $fragments["static_block_{$i}"] = [
                        'type' => 'static',
                        'size' => strlen($match),
                        'cacheable' => true
                    ];
                }
            }
        }

        return $fragments;
    }

    private function createFallbackAnalysis(string $template): TemplateAnalysis
    {
        return new TemplateAnalysis(
            $template,
            CacheStrategy::NO_CACHE,
            0,
            [],
            new CacheabilityScore(),
            []
        );
    }

    private function hasUserContent(string $content): bool
    {
        return preg_match('/\{\{\s*(user|auth|current_user)/', $content) > 0;
    }

    private function hasCsrfTokens(string $content): bool
    {
        return preg_match('/\{\{\s*(csrf_token|_token)/', $content) > 0;
    }

    private function hasTimestamps(string $content): bool
    {
        return preg_match('/\{\{\s*(now|timestamp|date\()/', $content) > 0;
    }

    private function hasRandomElements(string $content): bool
    {
        return preg_match('/\{\{\s*(random|rand\(|uuid)/', $content) > 0;
    }

    private function calculateStaticRatio(string $content): float
    {
        $totalLength = strlen($content);
        if ($totalLength === 0) return 0.0;

        // Entferne alle dynamischen Teile
        $staticContent = preg_replace('/\{\{.*?\}\}/', '', $content);
        $staticContent = preg_replace('/@\w+.*?@end\w+/s', '', $staticContent);

        return strlen($staticContent) / $totalLength;
    }

}
