<?php

declare(strict_types=1);

namespace App\Framework\View\Loading;

use App\Framework\Cache\Cache;
use App\Framework\Cache\CacheItem;
use App\Framework\Cache\CacheKey;
use App\Framework\Core\PathProvider;
use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Discovery\Results\DiscoveryRegistry;
use App\Framework\Filesystem\FileSystemService;
use App\Framework\View\Loading\Resolvers\ComponentResolver;
use App\Framework\View\Loading\Resolvers\ControllerResolver;
use App\Framework\View\Loading\Resolvers\DefaultPathResolver;
use App\Framework\View\Loading\Resolvers\DiscoveryResolver;
use App\Framework\View\Loading\Resolvers\LayoutResolver;
use App\Framework\View\Loading\Resolvers\TemplateMapResolver;
use App\Framework\View\RenderContext;

final readonly class TemplateLoader
{
    private TemplatePathResolver $pathResolver;

    private TemplateContentLoader $contentLoader;
    #private readonly TemplateCache $cache;

    public function __construct(
        private PathProvider      $pathProvider,
        private Cache             $cache,
        private ?DiscoveryRegistry $discoveryRegistry = null,
        private array             $templates = [],
        private string            $templatePath = '/src/Framework/View/templates',
        private bool              $useMtimeInvalidation = true,
        private bool              $cacheEnabled = false,  // Caching disabled for debugging
    ) {
        $this->pathResolver = $this->createPathResolver();
        $this->contentLoader = new TemplateContentLoader();
        #$this->cache = new TemplateCache();
    }

    private function createPathResolver(): TemplatePathResolver
    {
        $resolvers = [
            // 1. Explizite Template-Map (höchste Priorität)
            new TemplateMapResolver($this->templates),

            // 2. Discovery-basierte Templates (falls verfügbar)
            new DiscoveryResolver(new FileSystemService(), $this->discoveryRegistry),

            // 3. Layout-spezifische Suche (für "main" etc.)
            new LayoutResolver($this->pathProvider, $this->templatePath),

            // 4. Component-spezifische Suche
            new ComponentResolver($this->pathProvider, $this->templatePath),

            // 5. Controller-basierte Templates
            new ControllerResolver(),

            // 6. Standard-Pfad (Fallback)
            new DefaultPathResolver($this->pathProvider, $this->templatePath),
        ];

        return new TemplatePathResolver($resolvers);
    }

    public function load(string $template, ?string $controllerClass = null, ?RenderContext $context = null): string
    {
        error_log("TemplateLoader::load ENTRY - Template: $template, ControllerClass: " . ($controllerClass ?? 'null'));
        error_log("TemplateLoader::load - Cache enabled: " . ($this->cacheEnabled ? 'YES' : 'NO'));

        $resolvedPath = null;
        $mtimeSegment = '';

        if ($this->useMtimeInvalidation) {
            $resolvedPath = $this->pathResolver->resolve($template, $controllerClass);
            $mtime = is_string($resolvedPath) && is_file($resolvedPath) ? (int) @filemtime($resolvedPath) : 0;
            $mtimeSegment = $mtime > 0 ? (string) $mtime : '';
        }

        $cacheKey = $this->generateCacheKey($template, $controllerClass, $mtimeSegment);

        // Try cache first ONLY if caching is enabled
        if ($this->cacheEnabled) {
            $cached = $this->cache->get($cacheKey)->getItem($cacheKey);
            if ($cached->isHit && is_string($cached->value)) {
                error_log("TemplateLoader::load CACHE HIT - Template: $template, Cached content length: " . strlen($cached->value));
                error_log("TemplateLoader::load CACHE HIT - Cached content starts with: " . substr($cached->value, 0, 100));
                error_log("TemplateLoader::load CACHE HIT - Cached content contains '<layout': " . (strpos($cached->value, '<layout') !== false ? 'YES' : 'NO'));

                return $cached->value;
            }
        } else {
            error_log("TemplateLoader::load - Caching disabled, loading from filesystem");
        }

        // Load from filesystem
        $path = $resolvedPath ?? $this->pathResolver->resolve($template, $controllerClass);
        $content = $this->contentLoader->load($path);

        // Cache for future use (24 hours TTL) ONLY if caching is enabled
        if ($this->cacheEnabled) {
            $ttl = Duration::fromSeconds(86400);
            $this->cache->set(CacheItem::forSet($cacheKey, $content, $ttl));
            error_log("TemplateLoader::load - Content cached for template: $template");
        }

        error_log("TemplateLoader::load RETURN - Template: $template, Content length: " . strlen($content));
        error_log("TemplateLoader::load RETURN - Content starts with: " . substr($content, 0, 100));
        error_log("TemplateLoader::load RETURN - Content contains '<layout': " . (strpos($content, '<layout') !== false ? 'YES' : 'NO'));

        return $content;
    }

    public function getTemplatePath(string $template, ?string $controllerClass = null): string
    {
        return $this->pathResolver->resolve($template, $controllerClass);
    }

    public function clearCache(): void
    {
        $this->cache->clear();
    }

    public function getComponentPath(string $name): string
    {
        return $this->pathProvider->resolvePath($this->templatePath . "/components/{$name}.html");
    }

    public function debugTemplatePath(string $template, ?string $controllerClass = null): array
    {
        $debug = ['template' => $template, 'attempts' => []];

        /*$resolvers = [
            'TemplateMap' => new TemplateMapResolver($this->templates),
            'Discovery' => new DiscoveryResolver(new FileSystemService(), $this->discoveryRegistry),
            'Layout' => new LayoutResolver($this->pathProvider, $this->templatePath),
            'Component' => new ComponentResolver($this->pathProvider, $this->templatePath),
            'Controller' => new ControllerResolver(),
            'Default' => new DefaultPathResolver($this->pathProvider, $this->templatePath),
        ];*/

        $resolvers = $this->createPathResolver();

        foreach ($resolvers as $name => $resolver) {
            try {
                $path = $resolver->resolve($template, $controllerClass);
                $debug['attempts'][$name] = [
                    'path' => $path,
                    'exists' => $path && is_file($path),
                    'success' => $path && is_file($path),
                ];
            } catch (\Exception $e) {
                $debug['attempts'][$name] = ['error' => $e->getMessage()];
            }
        }

        return $debug;
    }

    private function generateCacheKey(string $template, ?string $controllerClass, string $mtimeSegment = ''): CacheKey
    {
        $parts = ['template', 'v1', $template];
        if ($controllerClass) {
            $parts[] = $controllerClass;
        }
        if ($mtimeSegment !== '') {
            $parts[] = $mtimeSegment;
        }

        return CacheKey::fromString(implode(':', $parts));
    }
}
