<?php

require_once __DIR__ . '/../../config/database.php';
require_once __DIR__ . '/../../config/helpers.php';
require_once __DIR__ . '/guest_inbox_transfer.php';

if (getMethod() !== 'POST') {
    jsonResponse(false, 'method.not_allowed', null, 405);
}

global $pdo;
$config = require __DIR__ . '/../../config/app.php';
$input = getJsonInput();

$identifier = strtolower(trim((string) ($input['username'] ?? $input['login'] ?? $input['email'] ?? '')));
$password = (string) ($input['password'] ?? '');
$guestAction = strtolower(trim((string) ($input['guest_action'] ?? 'fresh')));
$guestAccessToken = trim((string) ($input['guest_access_token'] ?? ''));
if ($guestAccessToken === '') {
    $guestAccessToken = (string) (getGuestInboxAccessToken($config) ?? '');
}

if ($identifier === '' || $password === '') {
    jsonResponse(false, 'username_password_required', null, 422);
}

$username = normalizeUsername($identifier);
$email = str_contains($identifier, '@') ? normalizeEmailAddress($identifier) : ($username !== '' ? buildUserInboxEmail($username, $config) : null);

$stmt = $pdo->prepare('SELECT * FROM users WHERE username = :username OR email = :email LIMIT 1');
$stmt->execute([
    'username' => $username,
    'email' => $email,
]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);

$ip = getClientIp();
$userAgent = getUserAgent();
$uaDetails = parseUserAgentDetails($userAgent);

if (!$user || !password_verify($password, $user['password'])) {
    if ($user) {
        $log = $pdo->prepare('INSERT INTO user_login_history (user_id, ip, device, browser, platform, user_agent, status, failure_reason) VALUES (:user_id, :ip, :device, :browser, :platform, :user_agent, :status, :failure_reason)');
        $log->execute([
            'user_id' => $user['id'],
            'ip' => $ip,
            'device' => $uaDetails['device'],
            'browser' => $uaDetails['browser'],
            'platform' => $uaDetails['platform'],
            'user_agent' => $userAgent,
            'status' => 'failed',
            'failure_reason' => 'invalid_credentials',
        ]);
    }

    jsonResponse(false, 'invalid_credentials', null, 401);
}

if ((int) ($user['is_active'] ?? 0) !== 1) {
    jsonResponse(false, 'user_inactive', null, 403);
}

$userEmail = (string) ($user['email'] ?? '');
if ($userEmail === '' && !empty($user['username'])) {
    $userEmail = buildUserInboxEmail((string) $user['username'], $config);
}

ensureUserInbox($pdo, (int) $user['id'], $userEmail);

$transferredInbox = null;
if ($guestAction === 'transfer' && $guestAccessToken !== '') {
    try {
        $transferredInbox = performGuestInboxTransfer($pdo, (int) $user['id'], $userEmail, $guestAction, $guestAccessToken);
        if ($transferredInbox !== null) {
            clearGuestInboxCookie($config);
        }
    } catch (Throwable $e) {
        jsonResponse(false, $e->getMessage() ?: 'guest_transfer_failed', null, 500);
    }
}

$token = generateToken(32);
$tokenHash = hashToken($token);
$expiresAt = date('Y-m-d H:i:s', strtotime('+' . ((int) ($config['auth']['session_ttl_days'] ?? 30)) . ' days'));

$sessionStmt = $pdo->prepare('INSERT INTO user_sessions (user_id, token_hash, ip, user_agent, device, platform, browser, expires_at, last_seen_at) VALUES (:user_id, :token_hash, :ip, :user_agent, :device, :platform, :browser, :expires_at, NOW())');
$sessionStmt->execute([
    'user_id' => $user['id'],
    'token_hash' => $tokenHash,
    'ip' => $ip,
    'user_agent' => $userAgent,
    'device' => $uaDetails['device'],
    'platform' => $uaDetails['platform'],
    'browser' => $uaDetails['browser'],
    'expires_at' => $expiresAt,
]);

$updateUser = $pdo->prepare('
    UPDATE users
    SET
        last_login_at = NOW(),
        last_login_ip = :last_login_ip,
        last_login_agent = :last_login_agent,
        ip = :current_ip,
        agent = :current_agent
    WHERE id = :id
');
$updateUser->execute([
    'last_login_ip' => $ip,
    'last_login_agent' => $userAgent,
    'current_ip' => $ip,
    'current_agent' => $userAgent,
    'id' => $user['id'],
]);

$log = $pdo->prepare('INSERT INTO user_login_history (user_id, ip, device, browser, platform, user_agent, status) VALUES (:user_id, :ip, :device, :browser, :platform, :user_agent, :status)');
$log->execute([
    'user_id' => $user['id'],
    'ip' => $ip,
    'device' => $uaDetails['device'],
    'browser' => $uaDetails['browser'],
    'platform' => $uaDetails['platform'],
    'user_agent' => $userAgent,
    'status' => 'success',
]);

setcookie($config['auth']['session_cookie'] ?? 'session_token', $token, [
    'expires' => strtotime($expiresAt),
    'path' => '/',
    'secure' => !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off',
    'httponly' => true,
    'samesite' => 'Lax',
]);

$freshUser = $pdo->prepare('SELECT * FROM users WHERE id = :id LIMIT 1');
$freshUser->execute(['id' => $user['id']]);
$user = $freshUser->fetch(PDO::FETCH_ASSOC) ?: $user;

jsonResponse(true, 'login_success', [
    'token' => $token,
    'expires_at' => $expiresAt,
    'user' => sanitizeUser($user),
    'guest_transfer_action' => $guestAction,
    'guest_transfer_completed' => $transferredInbox !== null,
    'linked_guest_inbox' => $transferredInbox,
]);
