<?php
/**
 * Front-controller Dispatcher
 *
 * Routes all public-page requests through a single entry point.
 * Admin panel (/admin/*) and static assets bypass the dispatcher.
 *
 * Routes:
 *   /                 → HomeController → home view
 *   /search.php       → SearchController → search view
 *   /repertoire       → SearchController → repertoire view
 *   /tfe/<id>         → TfeController → tfe view
 *   /apropos          → AboutController → about view
 *   /licence          → LicenceController → licence view
 *   /media.php        → MediaController (direct output)
 *   /live-reload      → LiveReloadController (direct output)
 *   /partage/<slug>   → share-link flow
 *   /maintenance.php  → static maintenance page
 */
class Dispatcher {
    private const ROUTES = [
        ''                       => ['controller' => 'HomeController',    'action' => 'handle',     'view' => 'public/home'],
        '/'                      => ['controller' => 'HomeController',    'action' => 'handle',     'view' => 'public/home'],
        '/index.php'             => ['controller' => 'HomeController',    'action' => 'handle',     'view' => 'public/home'],
        '/search'                => ['controller' => 'SearchController',  'action' => 'handleSearch',     'view' => 'public/search'],
        '/search.php'            => ['controller' => 'SearchController',  'action' => 'handleSearch',     'view' => 'public/search'],
        '/repertoire'            => ['controller' => 'SearchController',  'action' => 'handleRepertoire', 'view' => 'public/repertoire'],
        '/repertoire.php'        => ['controller' => 'SearchController',  'action' => 'handleRepertoire', 'view' => 'public/repertoire'],
        '/tfe'                   => ['controller' => 'TfeController',     'action' => 'handle',           'view' => 'public/tfe'],
        '/tfe.php'               => ['controller' => 'TfeController',     'action' => 'handle',           'view' => 'public/tfe'],
        '/apropos'               => ['controller' => 'AboutController',   'action' => 'handle',     'view' => 'public/about'],
        '/apropos.php'           => ['controller' => 'AboutController',   'action' => 'handle',     'view' => 'public/about'],
        '/licence'               => ['controller' => 'LicenceController', 'action' => 'handle',     'view' => 'public/licence'],
        '/licence.php'           => ['controller' => 'LicenceController', 'action' => 'handle',     'view' => 'public/licence'],
    ];

    private string $path;
    private array  $queryParams;

    public function __construct() {
        $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
        $this->path = $uri;
        $this->queryParams = $_GET;
    }

    /**
     * Resolve the URI to a route, instantiate the controller,
     * execute the action, and render the view.
     */
    public function dispatch(): void {
        // 1. Direct-response endpoints (render their own output)
        $direct = $this->matchDirect();
        if ($direct) {
            $direct();
            return;
        }

        // 2. Routed pages (controller + view)
        $route = $this->matchRoute();
        if (!$route) {
            http_response_code(404);
            echo '<h1>404 — Page non trouvée</h1>';
            return;
        }

        // 3. Load controller
        $ctrlClass = $route['controller'];
        require_once APP_ROOT . '/src/Controllers/' . $ctrlClass . '.php';

        $controller = $ctrlClass::create();
        $vars = $controller->{$route['action']}();

        // 4. Render view
        $this->render($route['view'], $vars);
    }

    /**
     * Match endpoints that render their own response (no view layer).
     */
    private function matchDirect(): ?callable {
        $path = $this->path;

        // /live-reload
        if ($path === '/live-reload' || $path === '/live-reload.php') {
            return function() {
                require_once APP_ROOT . '/src/Controllers/LiveReloadController.php';
                $controller = new LiveReloadController(APP_ROOT);
                $result = $controller->handle();
                header('Content-Type: application/json');
                echo json_encode($result['body']);
            };
        }

        // /media.php
        if ($path === '/media' || $path === '/media.php') {
            return function() {
                require_once APP_ROOT . '/src/Controllers/MediaController.php';
                $controller = new MediaController();
                $controller->handle();
            };
        }

        // /maintenance.php
        if ($path === '/maintenance' || $path === '/maintenance.php') {
            return function() {
                require APP_ROOT . '/public/maintenance.php';
            };
        }

        // /partage/*
        if (preg_match('#^/partage(/.*)?$#', $path)) {
            return function() {
                require APP_ROOT . '/public/partage/index.php';
            };
        }

        return null;
    }

    /**
     * Match the current path against the static route table.
     * Supports exact match and prefix-based (for /tfe?id=).
     */
    private function matchRoute(): ?array {
        $path = $this->path;

        // Exact match first
        if (isset(self::ROUTES[$path])) {
            return self::ROUTES[$path];
        }

        // /tfe?id= pattern (TfeController handles the id param internally)
        if (preg_match('#^/tfe$#', $path) && isset($_GET['id'])) {
            return self::ROUTES['/tfe'];
        }

        return null;
    }

    /**
     * Render a view template wrapped in the full page layout.
     * Includes head.php, header.php, the view, and footer.php.
     */
    private function render(string $view, array $vars): void {
        $viewPath = APP_ROOT . '/templates/' . $view . '.php';
        if (!file_exists($viewPath)) {
            http_response_code(500);
            echo "View not found: {$viewPath}";
            return;
        }
        extract($vars);
        include APP_ROOT . '/templates/head.php';
        include APP_ROOT . '/templates/header.php';
        include $viewPath;
        include APP_ROOT . '/templates/footer.php';
    }
}
