<?php

declare(strict_types=1);

namespace App\Core;

final class Router
{
    private array $routes = [];

    public function get(string $path, string $controller, string $method): void
    {
        $this->routes['GET'][$this->normalize($path)] = [$controller, $method];
    }

    public function post(string $path, string $controller, string $method): void
    {
        $this->routes['POST'][$this->normalize($path)] = [$controller, $method];
    }

    public function dispatch(): void
    {
        $method = strtoupper($_SERVER['REQUEST_METHOD'] ?? 'GET');
        $path = $this->normalize($_GET['page'] ?? '');

        $publicRoutes = [
            'login',
            'login_store',
        ];

        if (!Auth::check() && !in_array($path, $publicRoutes, true)) {
            Response::redirect('login');
        }

        if (Auth::check() && $path === 'login') {
            Response::redirect('dashboard');
        }

        if ($method === 'POST' && !Csrf::validate($_POST['_csrf'] ?? null)) {
            Session::flash('error', 'La session de sécurité a expiré. Merci de recommencer.');
            Response::redirect(Auth::check() ? 'dashboard' : 'login');
        }

        if (Auth::check() && $this->requiresAdministrator($path) && !Auth::hasRole('ADMINISTRATEUR')) {
            Session::flash('error', 'Accès réservé à un administrateur.');
            Response::redirect('dashboard');
        }

        [$controllerClass, $action] =
            $this->routes[$method][$path]
            ?? $this->routes['GET']['404'];

        $controller = new $controllerClass();
        $controller->$action();
    }

    private function requiresAdministrator(string $path): bool
    {
        if (str_starts_with($path, 'maintenance')) {
            return true;
        }

        if (str_starts_with($path, 'parametres')) {
            return true;
        }

        return in_array($path, [
            'utilisateurs',
            'utilisateurs_create',
            'utilisateurs_store',
            'utilisateurs_edit',
            'utilisateurs_update',
            'utilisateurs_deactivate',
        ], true);
    }

    private function normalize(string $path): string
    {
        return trim($path, '/');
    }
}
