<?php
http_response_code(403);
require_once __DIR__ . '/db.php';

function getClientIp(): string {
    $keys = [
        'HTTP_CF_CONNECTING_IP',
        'HTTP_X_REAL_IP',
        'HTTP_X_FORWARDED_FOR',
        'REMOTE_ADDR'
    ];

    foreach ($keys as $key) {
        if (!empty($_SERVER[$key])) {
            $value = $_SERVER[$key];

            if ($key === 'HTTP_X_FORWARDED_FOR') {
                $parts = explode(',', $value);
                $value = trim($parts[0]);
            }

            if (filter_var($value, FILTER_VALIDATE_IP)) {
                return $value;
            }
        }
    }

    return '0.0.0.0';
}

function getForwardedFor(): ?string {
    return $_SERVER['HTTP_X_FORWARDED_FOR'] ?? null;
}

function getRealIp(): ?string {
    return $_SERVER['HTTP_X_REAL_IP'] ?? null;
}

function isBot(string $ua): int {
    $bots = [
        'bot', 'crawl', 'spider', 'scanner', 'curl', 'wget', 'python',
        'sqlmap', 'nikto', 'nmap', 'masscan', 'zgrab', 'httpclient',
        'scrapy', 'headless', 'phantom', 'selenium'
    ];

    $ua = strtolower($ua);

    foreach ($bots as $bot) {
        if (strpos($ua, $bot) !== false) {
            return 1;
        }
    }
    return 0;
}

function parseBrowser(string $ua): string {
    $browsers = [
        'Edg' => 'Microsoft Edge',
        'OPR' => 'Opera',
        'Chrome' => 'Chrome',
        'Firefox' => 'Firefox',
        'Safari' => 'Safari',
        'MSIE' => 'Internet Explorer',
        'Trident' => 'Internet Explorer'
    ];

    foreach ($browsers as $key => $name) {
        if (stripos($ua, $key) !== false) {
            return $name;
        }
    }
    return 'Unknown';
}

function parseOS(string $ua): string {
    $systems = [
        'Windows NT 10.0' => 'Windows 10/11',
        'Windows NT 6.3'  => 'Windows 8.1',
        'Windows NT 6.1'  => 'Windows 7',
        'Android'         => 'Android',
        'iPhone'          => 'iPhone iOS',
        'iPad'            => 'iPad iOS',
        'Mac OS X'        => 'macOS',
        'Linux'           => 'Linux'
    ];

    foreach ($systems as $key => $name) {
        if (stripos($ua, $key) !== false) {
            return $name;
        }
    }
    return 'Unknown';
}

function parseDeviceType(string $ua): string {
    $ua = strtolower($ua);

    if (strpos($ua, 'tablet') !== false || strpos($ua, 'ipad') !== false) {
        return 'Tablet';
    }
    if (strpos($ua, 'mobile') !== false || strpos($ua, 'android') !== false || strpos($ua, 'iphone') !== false) {
        return 'Mobile';
    }
    return 'Desktop';
}

/**
 * Optional external country lookup.
 * For production, better use MaxMind GeoLite2 local database.
 * This function safely falls back to null values if lookup fails.
 */
function getGeoInfo(string $ip): array {
    $empty = [
        'country' => null,
        'city' => null,
        'region' => null,
        'hostname' => null,
    ];

    $hostname = @gethostbyaddr($ip);
    $empty['hostname'] = ($hostname && $hostname !== $ip) ? $hostname : null;

    // No external API by default
    return $empty;
}

$ip             = getClientIp();
$forwardedFor   = getForwardedFor();
$realIp         = getRealIp();
$requestUri     = $_SERVER['REQUEST_URI'] ?? '';
$scheme         = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host           = $_SERVER['HTTP_HOST'] ?? ($_SERVER['SERVER_NAME'] ?? '');
$fullUrl        = $scheme . '://' . $host . $requestUri;
$queryString    = $_SERVER['QUERY_STRING'] ?? '';
$requestMethod  = $_SERVER['REQUEST_METHOD'] ?? '';
$httpReferer    = $_SERVER['HTTP_REFERER'] ?? null;
$userAgent      = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
$acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? null;
$serverName     = $_SERVER['SERVER_NAME'] ?? null;
$remotePort     = $_SERVER['REMOTE_PORT'] ?? null;

$browser    = parseBrowser($userAgent);
$os         = parseOS($userAgent);
$deviceType = parseDeviceType($userAgent);
$bot        = isBot($userAgent);
$geo        = getGeoInfo($ip);

$logToken = bin2hex(random_bytes(16));
$now = date('Y-m-d H:i:s');

// Find previous count for same IP + same URI
$stmt = $pdo->prepare("
    SELECT attempt_count
    FROM forbidden_logs
    WHERE ip_address = :ip AND request_uri = :request_uri
    ORDER BY id DESC
    LIMIT 1
");
$stmt->execute([
    ':ip' => $ip,
    ':request_uri' => $requestUri
]);
$prev = $stmt->fetch();

$attemptCount = $prev ? ((int)$prev['attempt_count'] + 1) : 1;

$insert = $pdo->prepare("
    INSERT INTO forbidden_logs (
        log_token, ip_address, forwarded_for, real_ip, country, city, region, hostname,
        request_uri, full_url, query_string, request_method, http_referer, user_agent,
        browser, os, device_type, is_bot, accept_language, server_name, remote_port,
        attempt_count, created_at, updated_at
    ) VALUES (
        :log_token, :ip_address, :forwarded_for, :real_ip, :country, :city, :region, :hostname,
        :request_uri, :full_url, :query_string, :request_method, :http_referer, :user_agent,
        :browser, :os, :device_type, :is_bot, :accept_language, :server_name, :remote_port,
        :attempt_count, :created_at, :updated_at
    )
");

$insert->execute([
    ':log_token'        => $logToken,
    ':ip_address'       => $ip,
    ':forwarded_for'    => $forwardedFor,
    ':real_ip'          => $realIp,
    ':country'          => $geo['country'],
    ':city'             => $geo['city'],
    ':region'           => $geo['region'],
    ':hostname'         => $geo['hostname'],
    ':request_uri'      => $requestUri,
    ':full_url'         => $fullUrl,
    ':query_string'     => $queryString,
    ':request_method'   => $requestMethod,
    ':http_referer'     => $httpReferer,
    ':user_agent'       => $userAgent,
    ':browser'          => $browser,
    ':os'               => $os,
    ':device_type'      => $deviceType,
    ':is_bot'           => $bot,
    ':accept_language'  => $acceptLanguage,
    ':server_name'      => $serverName,
    ':remote_port'      => $remotePort,
    ':attempt_count'    => $attemptCount,
    ':created_at'       => $now,
    ':updated_at'       => $now
]);
?>
<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>403 Forbidden</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        body{
            font-family: Arial, sans-serif;
            background:#f3f5f8;
            color:#222;
            text-align:center;
            padding:40px 20px;
        }
        .box{
            max-width:900px;
            margin:0 auto;
            background:#fff;
            border-radius:12px;
            padding:30px;
            box-shadow:0 4px 20px rgba(0,0,0,.08);
        }
        h1{font-size:48px;margin:0 0 10px;}
        p{font-size:20px;line-height:1.6;}
        .small{font-size:14px;color:#666;margin-top:25px;}
    </style>
</head>
<body>
    <div class="box">
        <h1>403 Forbidden</h1>
        <p>You are not authorized to access this page.</p>
        <p>The access attempt has been logged.</p>
        <p class="small">Reference: <?php echo htmlspecialchars($logToken); ?></p>
    </div>

    <script>
    (function () {
        try {
            var data = new URLSearchParams();
            data.append('log_token', '<?php echo htmlspecialchars($logToken, ENT_QUOTES, 'UTF-8'); ?>');
            data.append('timezone_js', Intl.DateTimeFormat().resolvedOptions().timeZone || '');
            data.append('screen_resolution', (screen.width || '') + 'x' + (screen.height || ''));
            data.append('platform_js', navigator.platform || '');
            data.append('cookies_enabled', navigator.cookieEnabled ? 'yes' : 'no');

            navigator.sendBeacon('collect_client_info.php', data);
        } catch (e) {}
    })();
    </script>
</body>
</html>