<?php
declare(strict_types=1);

namespace App\Framework\View\Loading;

use App\Framework\Cache\Cache;
use App\Framework\Core\PathProvider;
use App\Framework\Discovery\Results\DiscoveryResults;
use App\Framework\Filesystem\FileStorage;
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\TemplateMapResolver;
use App\Framework\View\Loading\Resolvers\LayoutResolver;
use App\Framework\View\Loading\Resolvers\ComponentResolver;
use App\Framework\View\RenderContext;
use App\Framework\View\TemplateDiscoveryVisitor;

final class TemplateLoader
{
    private readonly TemplatePathResolver $pathResolver;
    private readonly TemplateContentLoader $contentLoader;
    #private readonly TemplateCache $cache;

    public function __construct(
        private readonly PathProvider $pathProvider,
        private readonly Cache $cache,
        private readonly ?DiscoveryResults $discoveryResults = null,
        private readonly array $templates = [],
        private readonly string $templatePath = '/src/Framework/View/templates',
        private readonly FileStorage $storage = new FileStorage,
        #private readonly ?TemplateDiscoveryVisitor $templateVisitor = null,
    ) {
        $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($this->discoveryResults),

            // 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
    {
        $cacheKey = 'template_content|' . $template . '|' . ($controllerClass ?? 'default');

        return $this->cache->remember($cacheKey, function() use ($template, $controllerClass, $context) {
            $path = $this->pathResolver->resolve($template, $controllerClass);
            $content = $this->contentLoader->load($path);
            return $content;
        })->value;

        if ($cached = $this->cache->get($cacheKey)) {
            return $cached;
        }

        $path = $this->pathResolver->resolve($template, $controllerClass);
        $content = $this->contentLoader->load($path);

        $this->cache->set($cacheKey, $content);
        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 __DIR__ . "/../templates/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($this->discoveryResults),
            'Layout' => new LayoutResolver($this->pathProvider, $this->templatePath),
            'Component' => new ComponentResolver($this->pathProvider, $this->templatePath),
            'Controller' => new ControllerResolver(),
            'Default' => new DefaultPathResolver($this->pathProvider, $this->templatePath),
        ];

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

        return $debug;
    }
}
