<?php
declare(strict_types=1);

namespace App\Core\Routing;

use App\Core\Router;
use RuntimeException;

final class RouteManager
{
    /** @var list<string> */
    private array $loadedFiles = [];

    public function __construct(
        private readonly Router $router,
        private readonly string $routesPath,
        private readonly ?string $cachePath = null,
    ) {
    }

    public function load(): void
    {
        foreach ($this->routeFiles() as $file) {
            $registrar = require $file;
            if (!is_callable($registrar)) {
                throw new RuntimeException('Le fichier de routes doit retourner une fonction : ' . $file);
            }
            $registrar($this->router);
            $this->loadedFiles[] = $file;
        }
        $this->writeCacheMetadata();
    }

    /** @return list<string> */
    public function loadedFiles(): array
    {
        return $this->loadedFiles;
    }

    /** @return array{routes:int,files:int,duplicates:list<string>,cache:?string} */
    public function summary(): array
    {
        return [
            'routes' => $this->router->count(),
            'files' => count($this->loadedFiles),
            'duplicates' => $this->router->duplicates(),
            'cache' => $this->cachePath,
        ];
    }

    /** @return list<string> */
    private function routeFiles(): array
    {
        $files = [];
        foreach (['web.php', 'api.php', 'core.php', 'studio.php'] as $name) {
            $file = rtrim($this->routesPath, '/\\') . DIRECTORY_SEPARATOR . $name;
            if (is_file($file)) {
                $files[] = $file;
            }
        }
        $moduleFiles = glob(rtrim($this->routesPath, '/\\') . '/modules/*.php') ?: [];
        sort($moduleFiles);
        return array_merge($files, $moduleFiles);
    }

    private function writeCacheMetadata(): void
    {
        if ($this->cachePath === null) {
            return;
        }
        $directory = dirname($this->cachePath);
        if (!is_dir($directory)) {
            @mkdir($directory, 0775, true);
        }
        if (!is_dir($directory) || !is_writable($directory)) {
            return;
        }
        $payload = [
            'generated_at' => date(DATE_ATOM),
            'files' => array_map(static fn(string $file): array => [
                'path' => $file,
                'mtime' => filemtime($file) ?: null,
                'sha256' => hash_file('sha256', $file) ?: null,
            ], $this->loadedFiles),
            'routes' => $this->router->all(),
        ];
        file_put_contents($this->cachePath, '<?php return ' . var_export($payload, true) . ';' . PHP_EOL, LOCK_EX);
    }
}
