<?php
/**
 * Unamused Login - Security Hardened
 */
define('UNAMUSED_APP', true);
require_once '../config/database.php';
require_once '../includes/functions.php';

// Start session with secure configuration
if (session_status() === PHP_SESSION_NONE) {
    $secure = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off';
    session_start([
        'cookie_lifetime' => 86400,
        'cookie_secure' => $secure,
        'cookie_httponly' => true,
        'cookie_samesite' => 'Strict',
        'use_strict_mode' => true,
        'use_only_cookies' => true,
        'cookie_path' => '/',
        'gc_maxlifetime' => 1800
    ]);
}

// Regenerate session ID periodically
if (isset($_SESSION['last_regeneration']) && (time() - $_SESSION['last_regeneration']) > 300) {
    session_regenerate_id(true);
    $_SESSION['last_regeneration'] = time();
} elseif (!isset($_SESSION['last_regeneration'])) {
    $_SESSION['last_regeneration'] = time();
}

// Already logged in check with validation
if (isset($_SESSION['user_id']) && is_int($_SESSION['user_id']) && $_SESSION['user_id'] > 0) {
    // Regenerate to prevent session fixation
    session_regenerate_id(true);
    header('Location: ../dashboard.php');
    exit();
}

// Get real client IP (respecting proxies safely)
$ip_address = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$ip_address = filter_var($ip_address, FILTER_VALIDATE_IP) ? $ip_address : 'unknown';

// Rate limiting
$max_attempts = 5;
$lockout_time = 15 * 60;
$errors = [];
$attempts = 0;

try {
    // Use hashed IP for privacy
    $hashedIp = hash('sha256', $ip_address);
    $stmt = $pdo->prepare("
        SELECT COUNT(*) as attempts 
        FROM login_attempts 
        WHERE ip_hash = ? AND success = 0 AND created_at > DATE_SUB(NOW(), INTERVAL ? SECOND)
    ");
    $stmt->execute([$hashedIp, $lockout_time]);
    $attempts = (int)($stmt->fetch()['attempts'] ?? 0);
} catch (PDOException $e) {
    error_log("Rate limit check failed: " . $e->getMessage());
}

if ($attempts >= $max_attempts) {
    $errors[] = "Too many failed attempts. Please try again later.";
    http_response_code(429);
}

// CSRF token
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    $_SESSION['csrf_token_time'] = time();
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && empty($errors)) {
    // Verify CSRF token with timing-safe comparison
    $token = $_POST['csrf_token'] ?? '';
    if (!hash_equals($_SESSION['csrf_token'] ?? '', $token)) {
        $errors[] = "Security token invalid. Please refresh and try again.";
        http_response_code(403);
    }
    
    // Check token age
    if (!isset($_SESSION['csrf_token_time']) || (time() - $_SESSION['csrf_token_time']) > 86400) {
        $errors[] = "Session expired. Please refresh and try again.";
    }
    
    // Get and validate email
    $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
    $password = $_POST['password'] ?? '';
    $remember_me = filter_input(INPUT_POST, 'remember_me', FILTER_VALIDATE_BOOLEAN) ?? false;
    
    if (empty($email)) {
        $errors[] = "Please enter a valid email address.";
    }
    if (strlen($password) < 1 || strlen($password) > 128) {
        $errors[] = "Invalid password.";
    }
    
    if (empty($errors)) {
        try {
            // Fetch user with row lock to prevent race conditions
            $stmt = $pdo->prepare("
                SELECT id, email, password_hash, first_name, email_verified, account_locked, failed_logins, last_failed_login
                FROM users 
                WHERE email = ? 
                LIMIT 1
            ");
            $stmt->execute([$email]);
            $user = $stmt->fetch();
            
            if (!$user || !password_verify($password, $user['password_hash'])) {
                // Log failed attempt with hashed IP
                $hashedIp = hash('sha256', $ip_address);
                $stmt = $pdo->prepare("
                    INSERT INTO login_attempts (ip_hash, email, success, created_at) 
                    VALUES (?, ?, 0, NOW())
                ");
                $stmt->execute([$hashedIp, strtolower($email)]);
                
                // Increment failed login count on user record
                if ($user) {
                    $stmt = $pdo->prepare("
                        UPDATE users 
                        SET failed_logins = failed_logins + 1, 
                            last_failed_login = NOW(),
                            account_locked = CASE WHEN failed_logins >= 4 THEN 1 ELSE account_locked END
                        WHERE id = ?
                    ");
                    $stmt->execute([$user['id']]);
                }
                
                // Generic error to prevent user enumeration
                $errors[] = "Invalid credentials.";
                usleep(random_int(100000, 300000)); // Timing attack mitigation
                goto end_login;
            }
            
            // Check account status
            if ($user['account_locked']) {
                $errors[] = "Account locked. Contact support.";
                goto end_login;
            }
            
            if (!$user['email_verified']) {
                $errors[] = "Please verify your email first.";
                $_SESSION['pending_verification_email'] = $user['email'];
                goto end_login;
            }
            
            // SUCCESS: Create session
            session_regenerate_id(true);
            $_SESSION['user_id'] = (int)$user['id'];
            $_SESSION['user_email'] = $user['email'];
            $_SESSION['user_first_name'] = htmlspecialchars($user['first_name'], ENT_QUOTES, 'UTF-8');
            $_SESSION['verified'] = true;
            $_SESSION['last_activity'] = time();
            $_SESSION['last_regeneration'] = time();
            
            // Clear failed logins
            $stmt = $pdo->prepare("UPDATE users SET failed_logins = 0 WHERE id = ?");
            $stmt->execute([$user['id']]);
            
            // Log success
            $hashedIp = hash('sha256', $ip_address);
            $stmt = $pdo->prepare("
                INSERT INTO login_attempts (ip_hash, email, success, created_at) 
                VALUES (?, ?, 1, NOW())
            ");
            $stmt->execute([$hashedIp, strtolower($email)]);
            
            // Remember me
            if ($remember_me) {
                $selector = bin2hex(random_bytes(12));
                $validator = bin2hex(random_bytes(32));
                $tokenHash = hash('sha256', $validator);
                $expires = date('Y-m-d H:i:s', time() + 30 * 86400);
                
                // Store token
                $stmt = $pdo->prepare("
                    INSERT INTO remember_tokens (user_id, selector, token_hash, expires_at) 
                    VALUES (?, ?, ?, ?)
                ");
                $stmt->execute([$user['id'], $selector, $tokenHash, $expires]);
                
                // Set cookie with selector:validator format
                $cookieValue = base64_encode($selector . ':' . $validator);
                setcookie('remember', $cookieValue, [
                    'expires' => time() + 30 * 86400,
                    'path' => '/',
                    'domain' => '',
                    'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
                    'httponly' => true,
                    'samesite' => 'Strict'
                ]);
            }
            
            header('Location: ../dashboard.php');
            exit();
            
        } catch (PDOException $e) {
            error_log("Login error: " . $e->getMessage());
            $errors[] = "System error. Please try again.";
        }
    }
}

end_login:
// Only regenerate CSRF on GET or after failed POST to prevent fixation
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !empty($errors)) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
    $_SESSION['csrf_token_time'] = time();
}

// Regenerate CSRF token for new form
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sign In | Unamused</title>
    
    <!-- Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    
    <!-- Lucide Icons -->
    <script src="https://unpkg.com/lucide@latest"></script>
    
    <!-- Google Fonts -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Crimson+Text:ital,wght@0,400;0,600;1,400&display=swap" rel="stylesheet">
    
    <style>
        :root {
            --color-bg: #fafaf9;
            --color-text: #1c1917;
            --color-accent: #dc2626;
            --color-border: #e7e5e4;
        }
        
        body {
            font-family: 'Inter', sans-serif;
            background-color: var(--color-bg);
            color: var(--color-text);
        }
        
        .font-serif {
            font-family: 'Crimson Text', serif;
        }
    </style>
</head>
<body class="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
    <div class="max-w-md w-full space-y-8 bg-white p-8 rounded-lg shadow-lg">
        <div>
            <a href="../index.html" class="flex items-center justify-center mb-6">
                <span class="text-2xl font-serif font-semibold">unamused<span class="text-red-600">.</span></span>
            </a>
            <h2 class="text-center text-3xl font-serif font-bold text-gray-900">
                Sign in to your account
            </h2>
            <p class="mt-2 text-center text-sm text-gray-600">
                Access your orders, saved items, and preferences
            </p>
        </div>
        
        <?php if (!empty($errors)): ?>
            <div class="bg-red-50 border-l-4 border-red-400 p-4 mb-4">
                <div class="flex">
                    <div class="flex-shrink-0">
                        <i data-lucide="alert-circle" class="h-5 w-5 text-red-400"></i>
                    </div>
                    <div class="ml-3">
                        <h3 class="text-sm font-medium text-red-800">Login failed</h3>
                        <div class="mt-2 text-sm text-red-700">
                            <ul class="list-disc pl-5 space-y-1">
                                <?php foreach ($errors as $error): ?>
                                    <li><?php echo htmlspecialchars($error); ?></li>
                                <?php endforeach; ?>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        <?php endif; ?>
        
        <form class="mt-8 space-y-6" method="POST" action="">
            <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
            
            <div class="rounded-md shadow-sm -space-y-px">
                <div>
                    <label for="email" class="sr-only">Email address</label>
                    <input id="email" name="email" type="email" autocomplete="email" required 
                           class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-t-md focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-gray-900 focus:z-10 sm:text-sm"
                           placeholder="Email address"
                           value="<?php echo isset($email) ? htmlspecialchars($email) : ''; ?>">
                </div>
                <div>
                    <label for="password" class="sr-only">Password</label>
                    <input id="password" name="password" type="password" autocomplete="current-password" required 
                           class="appearance-none rounded-none relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 rounded-b-md focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-gray-900 focus:z-10 sm:text-sm"
                           placeholder="Password">
                </div>
            </div>
            
            <div class="flex items-center justify-between">
                <div class="flex items-center">
                    <input id="remember_me" name="remember_me" type="checkbox" 
                           class="h-4 w-4 text-gray-900 focus:ring-gray-900 border-gray-300 rounded">
                    <label for="remember_me" class="ml-2 block text-sm text-gray-900">
                        Remember me
                    </label>
                </div>
                
                <div class="text-sm">
                    <a href="forgot-password.php" class="font-medium text-gray-900 hover:underline">
                        Forgot password?
                    </a>
                </div>
            </div>
            
            <div>
                <button type="submit" 
                        class="group relative w-full flex justify-center py-3 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-gray-900 hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-900">
                    <span class="absolute left-0 inset-y-0 flex items-center pl-3">
                        <i data-lucide="log-in" class="h-5 w-5 text-gray-300 group-hover:text-white"></i>
                    </span>
                    Sign in
                </button>
            </div>
        </form>
        
        <div class="text-center mt-4">
            <p class="text-sm text-gray-600">
                Don't have an account?
                <a href="register.php" class="font-medium text-gray-900 hover:underline">Sign up</a>
            </p>
        </div>
    </div>
    
    <!-- Lucide Icons -->
    <script src="https://unpkg.com/lucide@latest"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            if (typeof lucide !== 'undefined') {
                lucide.createIcons();
            }
        });
    </script>
</body>
</html>