<?php

namespace App\Twig;

use Detection\MobileDetect;
use Psr\Cache\CacheItemPoolInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class ViteAssetExtension extends AbstractExtension
{
    // Clé réservée dans le manifest Vite pour le HTML généré des favicons.
    const FAVICON_MANIFEST_KEY = '_FAVICONS_HTML_';

    private ?array $manifestData = null;

    const CACHE_KEY = 'vite_manifest';

    private readonly bool $isDev;

    public function __construct(
        private readonly string $manifest,
        private readonly CacheItemPoolInterface $cache,
    ) {
        // Respecte la logique existante : VITE_LOAD == "0" est considéré comme DEV.
        $this->isDev = $_ENV['VITE_LOAD'] == "0";
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('vite_asset', $this->asset(...), ['is_safe' => ['html']]),
            new TwigFunction('isMobile', $this->isMobile(...), ['is_safe' => ['html']]),
            // Nouvelle fonction Twig pour inclure les liens de favicons
            new TwigFunction('vite_favicons', $this->favicons(...), ['is_safe' => ['html']])
        ];
    }

    public function isMobile()
    {
        $detect = new MobileDetect();
        return $detect->isMobile() || $detect->isTablet();
    }

    /**
     * Charge le manifeste s'il n'est pas déjà chargé et met en cache.
     */
    private function loadManifest(): void
    {
        if ($this->manifestData === null) {
            $item = $this->cache->getItem(self::CACHE_KEY);
            if ($item->isHit()) {
                $this->manifestData = $item->get();
            } else {
                if (!file_exists($this->manifest)) {
                    // En cas d'erreur de fichier, initialise à un tableau vide
                    $this->manifestData = [];
                    return;
                }

                $this->manifestData = json_decode((string)file_get_contents($this->manifest), true);

                if (json_last_error() !== JSON_ERROR_NONE) {
                    $this->manifestData = [];
                }

                $item->set($this->manifestData);
                $this->cache->save($item);
            }
        }
    }

    // --- Gestion des assets JS/CSS (non modifiée) ---

    public function asset(string $entry, array $deps): string
    {
        if ($this->isDev) {
            return $this->assetDev($entry, $deps);
        }

        return $this->assetProd($entry);
    }

    public function assetDev(string $entry, array $deps): string
    {
        $html = <<<HTML
            <script type="module" src="http://localhost:5173/assets/@vite/client"></script>
            HTML;
        return $html . <<<HTML
            <script type="module" src="http://localhost:5173/assets/{$entry}" defer></script>
            HTML;
    }

    public function assetProd(string $entry): string
    {
        $this->loadManifest();

        $file = $this->manifestData[$entry]['file'] ?? '';
        $css = $this->manifestData[$entry]['css'] ?? [];
        $imports = $this->manifestData[$entry]['imports'] ?? [];

        $html = <<<HTML
            <script type="module" src="/build/{$file}" crossorigin="anonymous" defer></script>
            HTML;

        foreach ($css as $cssFile) {
            $html .= <<<HTML
            <link rel="stylesheet" rel="preload" media="screen" href="/build/{$cssFile}" crossorigin="anonymous"/>
            HTML;
        }

        foreach ($imports as $import) {
            $import = str_replace("_vendor","vendor",$import);
            $import = str_replace("_turbo","turbo",$import);
            $html .= <<<HTML
            <link rel="modulepreload" href="/build/{$import}" crossorigin="anonymous"/>
            HTML;
        }

        return $html;
    }

    // --- Nouvelle Gestion des Favicons ---

    public function favicons(): string
    {
        if ($this->isDev) {
            return $this->faviconsDev();
        }

        return $this->faviconsProd();
    }

    public function faviconsDev(): string
    {
        // En mode dev, on assume qu'un fichier favicon.ico ou favicon.png
        // standard est présent dans le répertoire public.
        return <<<HTML
            <link rel="icon" type="image/x-icon" href="/favicon.ico">
            HTML;
    }

    public function faviconsProd(): string
    {
        $this->loadManifest();

        // Récupère le bloc HTML complet généré par le plugin dans le manifest.
        // On suppose que l'entrée est un tableau associatif avec la clé 'html'.
        $faviconData = $this->manifestData;
        $faviconHtml = "";
        foreach ($faviconData as $key =>$favicon) {
            if(!str_contains($key,".js")) {
                $faviconHtml .= <<<HTML
                    <link rel="icon" href="/build/{$favicon['file']}" type="image/x-icon">
                HTML;
            }
        }
        return $faviconHtml;
    }
}
