<?php

declare(strict_types=1);

final class AuthController
{
    public static function logo(): void
    {
        header('Content-Type: image/png');
        header('Cache-Control: public,max-age=86400');
        readfile(__DIR__ . '/../../resources/branding/Logo_Globinours_maxi.png');
        exit();
    }
    public static function pwaIcon(int $size): void
    {
        $size = in_array($size, [192, 512], true) ? $size : 192;
        $source = __DIR__ . '/../../resources/branding/Logo_Globinours_maxi.png';
        if (!extension_loaded('gd') || !is_file($source)) {
            self::logo();
            return;
        }
        $src = imagecreatefrompng($source);
        if (!$src) {
            self::logo();
            return;
        }
        $dst = imagecreatetruecolor($size, $size);
        imagesavealpha($dst, true);
        $transparent = imagecolorallocatealpha($dst, 0, 0, 0, 127);
        imagefill($dst, 0, 0, $transparent);
        $sw = imagesx($src);
        $sh = imagesy($src);
        $ratio = min(($size * 0.88) / $sw, ($size * 0.88) / $sh);
        $w = (int) round($sw * $ratio);
        $h = (int) round($sh * $ratio);
        imagecopyresampled($dst, $src, (int) (($size - $w) / 2), (int) (($size - $h) / 2), 0, 0, $w, $h, $sw, $sh);
        header('Content-Type: image/png');
        header('Cache-Control: public,max-age=604800,immutable');
        imagepng($dst);
        imagedestroy($src);
        imagedestroy($dst);
        exit();
    }
    public static function setup(): void
    {
        if (Auth::countUsers() > 0) {
            header('Location: /login');
            exit();
        }
        $error = null;
        $checks = InstallationService::runtimeChecks();
        $canInstall = InstallationService::canInstall($checks);
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
            if (!Auth::validCsrf($_POST['csrf'] ?? null)) {
                $error = t('auth.session_expired');
            } elseif (!$canInstall) {
                $error = t('install.requirements_block');
            } else {
                $username = trim((string) ($_POST['username'] ?? ''));
                $display = trim((string) ($_POST['display_name'] ?? ''));
                $password = (string) ($_POST['password'] ?? '');
                $confirm = (string) ($_POST['password_confirm'] ?? '');
                $association = trim((string) ($_POST['association_name'] ?? ''));
                $email = trim((string) ($_POST['association_email'] ?? ''));
                $language = (string) ($_POST['app_language'] ?? 'fr');
                $routing = (string) ($_POST['public_site_routing'] ?? 'integrated');
                if ($association === '') {
                    $error = t('install.association_required');
                } elseif ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
                    $error = t('settings.invalid_email');
                } elseif (!preg_match('/^[a-zA-Z0-9._-]{3,40}$/', $username)) {
                    $error = t('auth.invalid_username');
                } elseif ($display === '') {
                    $error = t('auth.display_required');
                } elseif (strlen($password) < 10) {
                    $error = t('auth.password_min', ['count' => 10]);
                } elseif ($password !== $confirm) {
                    $error = t('auth.password_mismatch');
                } else {
                    $db = DB::pdo();
                    try {
                        $db->beginTransaction();
                        $db->prepare(
                            "INSERT INTO users(username,password_hash,display_name,role) VALUES(:u,:p,:d,'admin')",
                        )->execute([
                            ':u' => $username,
                            ':p' => password_hash($password, PASSWORD_DEFAULT),
                            ':d' => $display,
                        ]);
                        AppSettings::save(
                            [
                                'association_name' => $association,
                                'association_address' => trim((string) ($_POST['association_address'] ?? '')),
                                'association_postal_code' => trim((string) ($_POST['association_postal_code'] ?? '')),
                                'association_city' => trim((string) ($_POST['association_city'] ?? '')),
                                'association_phone' => trim((string) ($_POST['association_phone'] ?? '')),
                                'association_email' => $email,
                                'association_siret' => trim((string) ($_POST['association_siret'] ?? '')),
                                'association_rna' => trim((string) ($_POST['association_rna'] ?? '')),
                                'app_language' => isset(I18n::LOCALES[$language]) ? $language : 'fr',
                                'public_site_routing' => in_array($routing, ['integrated', 'root'], true)
                                    ? $routing
                                    : 'integrated',
                            ],
                            (int) $db->lastInsertId(),
                        );
                        $db->commit();
                        Auth::login($username, $password);
                        AuditService::log(
                            'setup',
                            '/setup',
                            'Installation initiale et création du premier administrateur',
                            'user',
                            Auth::id(),
                        );
                        header('Location: /settings/health?installed=1');
                        exit();
                    } catch (Throwable $e) {
                        if ($db->inTransaction()) {
                            $db->rollBack();
                        }
                        $error = SecurityService::publicError($e);
                    }
                }
            }
        }
        self::view(t('auth.first_setup'), 'setup', $error, [
            'checks' => $checks,
            'canInstall' => $canInstall,
            'publicPath' => InstallationService::publicPath(),
        ]);
    }
    public static function setupUnavailable(array $checks): void
    {
        self::view(t('auth.first_setup'), 'setup', $error = t('install.runtime_missing'), [
            'checks' => $checks,
            'canInstall' => false,
            'publicPath' => InstallationService::publicPath(),
        ]);
    }
    public static function login(): void
    {
        if (Auth::countUsers() === 0) {
            header('Location: /setup');
            exit();
        }
        if (Auth::user()) {
            header('Location: ' . PermissionService::firstAllowedPath());
            exit();
        }
        $error = null;
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
            if (!Auth::validCsrf($_POST['csrf'] ?? null)) {
                $error = t('auth.session_expired');
            } elseif (
                Auth::login(
                    (string) ($_POST['username'] ?? ''),
                    (string) ($_POST['password'] ?? ''),
                    isset($_POST['remember_device']),
                    (string) ($_POST['device_name'] ?? ''),
                )
            ) {
                AuditService::log('login', '/login', 'Connexion réussie');
                $next = (string) ($_POST['next'] ?? '');
                if (
                    !str_starts_with($next, '/') ||
                    str_starts_with($next, '//') ||
                    !PermissionService::canOpenPath((string) (parse_url($next, PHP_URL_PATH) ?: '/'))
                ) {
                    $next = PermissionService::firstAllowedPath();
                }
                header('Location: ' . $next);
                exit();
            } else {
                AuditService::log('login_failed', '/login', 'Échec de connexion', null, null, [
                    'username_hash' => hash('sha256', mb_strtolower(trim((string) ($_POST['username'] ?? '')))),
                ]);
                $error = t('auth.invalid_credentials');
            }
        }
        self::view(t('auth.login'), 'login', $error);
    }
    public static function logout(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST' || !Auth::validCsrf($_POST['csrf'] ?? null)) {
            http_response_code(400);
            return;
        }
        AuditService::log('logout', '/logout', 'Déconnexion');
        Auth::logout();
        header('Location: /login');
        exit();
    }
    private static function view(string $title, string $mode, ?string $error, array $vars = []): void
    {
        extract($vars, EXTR_SKIP);
        require __DIR__ . '/../Views/auth.php';
    }
}
