<?php
require_once __DIR__ . '/../../config.php';
require_once __DIR__ . '/db.php';

/**
 * ---------- SESSION ----------
 */
function auth_session_start(): void {
    if (session_status() === PHP_SESSION_NONE) {
        session_set_cookie_params([
            'lifetime' => SERVICE_SESSION_TTL,
            'path'     => '/service/',
            'secure'   => !empty($_SERVER['HTTPS']),
            'httponly' => true,
            'samesite' => 'Strict',
        ]);
        session_name('AEGIS_SRV');
        session_start();
    }
}

/**
 * ---------- LOGIN ----------
 */
define('BRUTE_FORCE_WINDOW', 180);
define('BRUTE_FORCE_MAX_ATTEMPTS', 3);

function auth_brute_force_check(string $login): bool {
    $pdo = getDB();
    $stmt = $pdo->prepare("SELECT COUNT(*) FROM login_attempts WHERE (login = ? OR ip_address = ?) AND attempt_time > NOW() - CAST(? || ' seconds' AS INTERVAL)");
    $stmt->execute([$login, $_SERVER['REMOTE_ADDR'] ?? '', BRUTE_FORCE_WINDOW]);
    return $stmt->fetchColumn() >= BRUTE_FORCE_MAX_ATTEMPTS;
}

function auth_record_attempt(string $login): void {
    $pdo = getDB();
    $stmt = $pdo->prepare("INSERT INTO login_attempts (ip_address, login) VALUES (?, ?)");
    $stmt->execute([$_SERVER['REMOTE_ADDR'] ?? '', $login]);
}

function auth_clear_attempts(string $login): void {
    $pdo = getDB();
    $stmt = $pdo->prepare("DELETE FROM login_attempts WHERE login = ? OR ip_address = ?");
    $stmt->execute([$login, $_SERVER['REMOTE_ADDR'] ?? '']);
}

function auth_login(string $login, string $password): array {
    $pdo = getDB();

    if (auth_brute_force_check($login)) {
        return ['success' => false, 'error' => 'Превышен лимит попыток. Подождите 3 минуты.'];
    }

    $stmt = $pdo->prepare("SELECT id, login, password_hash, role, full_name, is_active FROM users WHERE login = ? LIMIT 1");
    $stmt->execute([$login]);
    $user = $stmt->fetch();

    if (!$user || !password_verify($password, $user['password_hash'])) {
        auth_record_attempt($login);
        return ['success' => false, 'error' => 'Неверный логин или пароль.'];
    }

    if (!$user['is_active']) {
        return ['success' => false, 'error' => 'Учётная запись заблокирована.'];
    }

    auth_clear_attempts($login);

    $_SESSION['user_id']    = (int)$user['id'];
    $_SESSION['user_login'] = $user['login'];
    $_SESSION['user_role']  = $user['role'];
    $_SESSION['user_name']  = $user['full_name'];
    $_SESSION['auth_time']  = time();
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));

    auth_log($user['id'], 'login', 'Вход в систему');

    return ['success' => true];
}

/**
 * ---------- LOGOUT ----------
 */
function auth_logout(): void {
    if (!empty($_SESSION['user_id'])) {
        auth_log($_SESSION['user_id'], 'logout', 'Выход из системы');
    }
    $_SESSION = [];
    if (ini_get('session.use_cookies')) {
        setcookie(session_name(), '', time() - 42000, '/service/');
    }
    session_destroy();
}

/**
 * ---------- GUARD ----------
 */
function auth_require(): array {
    auth_session_start();
    $allowed_roles = func_get_args();
    if (empty($_SESSION['user_id'])) {
        header('Location: /service/index.php?redirect=' . urlencode($_SERVER['REQUEST_URI']));
        exit;
    }
    if (!empty($allowed_roles) && !in_array($_SESSION['user_role'], $allowed_roles, true)) {
        http_response_code(403);
        require __DIR__ . '/../pages/shared/403.php';
        exit;
    }
    return $_SESSION;
}

function auth_has_role(string $role): bool {
    return isset($_SESSION['user_role']) && $_SESSION['user_role'] === $role;
}

/**
 * ---------- CSRF ----------
 */
function auth_csrf_token(): string {
    return $_SESSION['csrf_token'] ?? '';
}

function auth_csrf_verify(string $token): bool {
    return hash_equals($_SESSION['csrf_token'] ?? '', $token);
}

/**
 * ---------- AUDIT LOG ----------
 */
function auth_log(?int $userId, string $action, string $details = ''): void {
    try {
        $pdo = getDB();
        $stmt = $pdo->prepare("INSERT INTO audit_log (user_id, action, details, ip_address) VALUES (?, ?, ?, ?)");
        $stmt->execute([$userId, $action, $details, $_SERVER['REMOTE_ADDR'] ?? '']);
    } catch (\Throwable $e) {
        // silent
    }
}
