<?php

namespace App\Framework\View\Loading\Resolvers;

use App\Framework\Discovery\Results\DiscoveryResults;
use App\Framework\View\TemplateDiscoveryVisitor;

final readonly class DiscoveryResolver implements TemplateResolverStrategy
{
    const string TEMPLATE_EXTENSION = '.view.php';

    public function __construct(
        private DiscoveryResults|null $discoverySource = null
    ) {}

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

        return $this->resolveFromDiscoveryResults($template, $controllerClass);
    }

    private function resolveFromDiscoveryResults(string $template, ?string $controllerClass): ?string
    {
        $templates = $this->discoverySource->getTemplates();

        // Strategie 1: Direkter Template-Name-Match
        if (isset($templates[$template])) {
            return $this->selectBestTemplate($templates[$template], $controllerClass);
        }

        // Strategie 2: Template mit Extension
        $templateWithExt = $template . self::TEMPLATE_EXTENSION;
        if (isset($templates[$templateWithExt])) {
            return $this->selectBestTemplate($templates[$templateWithExt], $controllerClass);
        }

        // Strategie 3: Suche in allen Templates
        foreach ($templates as $templateName => $templateData) {
            if ($this->templateMatches($templateName, $template)) {
                return $this->selectBestTemplate($templateData, $controllerClass);
            }
        }

        return null;
    }

    private function resolveFromTemplateVisitor(string $template, ?string $controllerClass): ?string
    {
        $path = $this->discoverySource->getTemplatePath($template, $controllerClass);
        return ($path && file_exists($path)) ? $path : null;
    }

    private function selectBestTemplate(mixed $templateData, ?string $controllerClass): ?string
    {
        // Wenn templateData ein String ist (direkter Pfad)
        if (is_string($templateData)) {
            return file_exists($templateData) ? $templateData : null;
        }

        // Wenn templateData ein Array ist (mehrere Varianten)
        if (is_array($templateData)) {
            // 1. Versuche Controller-spezifisches Template
            if ($controllerClass && isset($templateData[$controllerClass])) {
                $path = $templateData[$controllerClass];
                if (is_string($path) && file_exists($path)) {
                    return $path;
                }
            }

            // 2. Versuche Standard-Template (leerer Key)
            if (isset($templateData[''])) {
                $path = $templateData[''];
                if (is_string($path) && file_exists($path)) {
                    return $path;
                }
            }

            // 3. Nimm das erste verfügbare Template
            foreach ($templateData as $path) {
                if (is_string($path) && file_exists($path)) {
                    return $path;
                }
            }
        }

        return null;
    }

    private function templateMatches(string $templateName, string $searchTemplate): bool
    {
        // Entferne Extension für Vergleich
        $cleanTemplateName = str_replace(self::TEMPLATE_EXTENSION, '', $templateName);

        return $cleanTemplateName === $searchTemplate ||
               basename($cleanTemplateName) === $searchTemplate ||
               str_contains($cleanTemplateName, $searchTemplate);
    }
}
