<?php
declare(strict_types=1);

/**
 * /includes/security.php
 * Security helpers:
 * - logging login attempts into security_login_log
 * - small helpers for IP/UA normalization
 *
 * Використання:
 *   require_once __DIR__ . '/security.php';
 *   security_log_login_attempt(db(), true,  $reason, $userId, $email);
 *   security_log_login_attempt(db(), false, $reason, null,  $email);
 */

if (!function_exists('security_client_ip')) {
    function security_client_ip(): string
    {
        // У нас довіра тільки до REMOTE_ADDR (без X-Forwarded-For), щоб не підробляли.
        $ip = (string)($_SERVER['REMOTE_ADDR'] ?? '');
        $ip = trim($ip);
        if ($ip === '') return '0.0.0.0';
        if (strlen($ip) > 45) $ip = substr($ip, 0, 45);
        return $ip;
    }
}

if (!function_exists('security_user_agent')) {
    function security_user_agent(): string
    {
        $ua = (string)($_SERVER['HTTP_USER_AGENT'] ?? '');
        $ua = trim($ua);
        if ($ua === '') $ua = '-';
        // 255 — як у колонці
        if (strlen($ua) > 255) $ua = substr($ua, 0, 255);
        return $ua;
    }
}

if (!function_exists('security_has_table')) {
    function security_has_table(PDO $pdo, string $table): bool
    {
        if (!preg_match('/^[a-zA-Z0-9_]+$/', $table)) return false;
        try {
            $st = $pdo->prepare("
                SELECT COUNT(*)
                FROM information_schema.tables
                WHERE table_schema = DATABASE()
                  AND table_name = ?
            ");
            $st->execute([$table]);
            return ((int)$st->fetchColumn() > 0);
        } catch (Throwable $e) {
            return false;
        }
    }
}

if (!function_exists('security_log_login_attempt')) {
    function security_log_login_attempt(
        PDO $pdo,
        bool $ok,
        string $reason = '',
        ?int $userId = null,
        ?string $email = null,
        ?string $countryCode = null,
        ?string $city = null
    ): void {
        try {
            if (!security_has_table($pdo, 'security_login_log')) return;

            $ip = security_client_ip();
            $ua = security_user_agent();

            $reason = trim($reason);
            if ($reason === '') $reason = null;

            $email = $email !== null ? trim($email) : null;
            if ($email === '') $email = null;
            if ($email !== null && strlen($email) > 190) $email = substr($email, 0, 190);

            $countryCode = $countryCode !== null ? strtoupper(trim($countryCode)) : null;
            if ($countryCode === '') $countryCode = null;
            if ($countryCode !== null && strlen($countryCode) > 2) $countryCode = substr($countryCode, 0, 2);

            $city = $city !== null ? trim($city) : null;
            if ($city === '') $city = null;
            if ($city !== null && strlen($city) > 120) $city = substr($city, 0, 120);

            $st = $pdo->prepare("
                INSERT INTO security_login_log
                    (user_id, email, ip, ua, ok, reason, country_code, city, created_at)
                VALUES
                    (:user_id, :email, :ip, :ua, :ok, :reason, :cc, :city, NOW())
            ");
            $st->execute([
                ':user_id' => $userId,
                ':email'   => $email,
                ':ip'      => $ip,
                ':ua'      => $ua,
                ':ok'      => $ok ? 1 : 0,
                ':reason'  => $reason,
                ':cc'      => $countryCode,
                ':city'    => $city,
            ]);
        } catch (Throwable $e) {
            // Security log не повинен ламати логін.
        }
    }
}