<?php

declare(strict_types=1);

class Auth
{
    private static ?array $currentUser = null;

    

    public static function passwordAlgo(): string
    {
        return defined('PASSWORD_ARGON2ID') ? PASSWORD_ARGON2ID : PASSWORD_DEFAULT;
    }

    public static function hashPassword(string $password): string
    {
        return password_hash($password, self::passwordAlgo());
    }

    public static function register(string $username, string $email, string $password): array
    {
        $username = trim($username);
        $email = trim(strtolower($email));

        if (mb_strlen($username) < 3 || mb_strlen($username) > 50) {
            return ['success' => false, 'error' => __('error_username_length')];
        }

        if (!preg_match('/^[a-zA-Z0-9_-]+$/', $username)) {
            return ['success' => false, 'error' => __('error_username_chars')];
        }

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            return ['success' => false, 'error' => __('error_invalid_email')];
        }

        if (mb_strlen($password) < 8) {
            return ['success' => false, 'error' => __('error_password_length')];
        }

        $existing = Database::fetchOne(
            'SELECT id FROM users WHERE username = ? OR email = ?',
            [$username, $email]
        );

        if ($existing !== null) {
            return ['success' => false, 'error' => __('error_username_taken')];
        }

        $passwordHash = self::hashPassword($password);

        $userId = Database::insert('users', [
            'username'      => $username,
            'email'         => $email,
            'password_hash' => $passwordHash,
            'role'          => 'user',
            'is_active'     => 1,
        ]);

        self::createSession($userId);

        return ['success' => true, 'error' => ''];
    }

    public static function login(string $login, string $password): array
    {
        $login = trim($login);

        if ($login === '' || $password === '') {
            return ['success' => false, 'error' => __('error_fill_all_fields')];
        }

        $user = Database::fetchOne(
            'SELECT * FROM users WHERE LOWER(email) = LOWER(?) OR username = ?',
            [$login, $login]
        );

        if ($user === null || !password_verify($password, $user['password_hash'])) {
            return ['success' => false, 'error' => __('error_invalid_credentials')];
        }

        if ((int) $user['is_active'] !== 1) {
            return ['success' => false, 'error' => __('error_account_deactivated')];
        }

         
        if (password_needs_rehash($user['password_hash'], self::passwordAlgo())) {
            $newHash = self::hashPassword($password);
            Database::update('users', ['password_hash' => $newHash], 'id = ?', [(int) $user['id']]);
        }

        self::createSession((int) $user['id']);

        return ['success' => true, 'error' => ''];
    }

    public static function logout(): void
    {
        self::$currentUser = null;
        $_SESSION = [];

        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
        }

        session_destroy();
    }

    public static function user(): ?array
    {
        if (self::$currentUser !== null) {
            return self::$currentUser;
        }

        if (!isset($_SESSION['user_id'])) {
            return null;
        }

        $user = Database::fetchOne('SELECT * FROM users WHERE id = ? AND is_active = 1', [$_SESSION['user_id']]);

        if ($user === null) {
            unset($_SESSION['user_id']);
            return null;
        }

        self::$currentUser = $user;
        return self::$currentUser;
    }

    public static function check(): bool
    {
        return self::user() !== null;
    }

    public static function isAdmin(): bool
    {
        $user = self::user();
        return $user !== null && in_array($user['role'], ['admin', 'moderator'], true);
    }

    public static function requireAuth(): void
    {
        if (!self::check()) {
            header('Location: ' . Router::url('/login'));
            exit;
        }
    }

    public static function requireAdmin(): void
    {
        if (!self::isAdmin()) {
            header('Location: ' . AdminController::loginUrl());
            exit;
        }
         
         
         
         
        $u = self::user();
        if (!empty($u['totp_secret']) && empty($_SESSION['2fa_verified'])) {
            header('Location: ' . AdminController::loginUrl() . '/2fa');
            exit;
        }
    }

    

    public static function requireSuperAdmin(): void
    {
        self::requireAdmin();  
        if ((self::user()['role'] ?? '') !== 'admin') {
            http_response_code(403);
            if (class_exists('ThemeRenderer', false) && App::isInstalled()) {
                try { ThemeRenderer::render('403', ['pageTitle' => '403 Forbidden']); }
                catch (\Throwable) { echo '<h1>403 Forbidden</h1>'; }
            } else {
                echo '<h1>403 Forbidden</h1>';
            }
            exit;
        }
    }

    public static function id(): ?int
    {
        $user = self::user();
        return $user !== null ? (int) $user['id'] : null;
    }

    private static function createSession(int $userId): void
    {
        session_regenerate_id(true);
        $_SESSION['user_id'] = $userId;
        self::$currentUser = null;
    }
}
