<?php

declare(strict_types=1);

namespace App\Auth;

use App\Database;
use PDO;

final class AdminAuth
{
    private PDO $db;

    public function __construct()
    {
        $this->db = Database::connection();
    }

    public function attempt(string $username, string $password): bool
    {
        $statement = $this->db->prepare(
            'SELECT id, username, display_name, password_hash, is_active, failed_attempts, locked_until
             FROM admins WHERE username = :username LIMIT 1'
        );
        $statement->execute(['username' => $username]);
        $admin = $statement->fetch();

        if (!$admin) {
            password_verify($password, password_hash('invalid-login', PASSWORD_DEFAULT));
            return false;
        }

        if (!(bool) $admin['is_active']) {
            return false;
        }

        if ($admin['locked_until'] && strtotime($admin['locked_until']) > time()) {
            return false;
        }

        if (!password_verify($password, $admin['password_hash'])) {
            $failed = (int) $admin['failed_attempts'] + 1;
            $lockedUntil = $failed >= 5 ? date('Y-m-d H:i:s', time() + 900) : null;
            $update = $this->db->prepare('UPDATE admins SET failed_attempts = :failed, locked_until = :locked WHERE id = :id');
            $update->execute(['failed' => $failed >= 5 ? 0 : $failed, 'locked' => $lockedUntil, 'id' => $admin['id']]);
            return false;
        }

        $update = $this->db->prepare('UPDATE admins SET failed_attempts = 0, locked_until = NULL, last_login_at = NOW() WHERE id = :id');
        $update->execute(['id' => $admin['id']]);
        session_regenerate_id(true);
        $_SESSION['admin'] = [
            'id' => (int) $admin['id'],
            'username' => $admin['username'],
            'display_name' => $admin['display_name'],
            'authenticated_at' => time(),
        ];
        return true;
    }

    public static function check(): bool
    {
        return isset($_SESSION['admin']['id'], $_SESSION['admin']['authenticated_at'])
            && time() - (int) $_SESSION['admin']['authenticated_at'] < 7200;
    }

    public static function requireLogin(): void
    {
        if (!self::check()) {
            unset($_SESSION['admin']);
            redirect('/admin/login');
        }
        $_SESSION['admin']['authenticated_at'] = time();
    }

    public static function logout(): void
    {
        unset($_SESSION['admin']);
        session_regenerate_id(true);
    }
}
