<?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();

$rawUsername = trim((string) ($input['username'] ?? $input['email'] ?? ''));
$username = normalizeUsername($rawUsername);
$name = trim((string) ($input['name'] ?? $username));
$email = $username !== '' ? buildUserInboxEmail($username, $config) : '';
$password = (string) ($input['password'] ?? '');
$phone = trim((string) ($input['phone'] ?? ''));
$country = trim((string) ($input['country'] ?? ''));
$avatar = trim((string) ($input['avatar'] ?? ''));
$guestAction = strtolower(trim((string) ($input['guest_action'] ?? 'transfer')));
$guestAccessToken = trim((string) ($input['guest_access_token'] ?? ''));
if ($guestAccessToken === '') {
    $guestAccessToken = (string) (getGuestInboxAccessToken($config) ?? '');
}

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

if (!isValidInboxUsername($username)) {
    jsonResponse(false, 'invalid_username', [
        'rules' => 'Username must be 3-32 chars and use letters, numbers, dot, dash, or underscore.',
    ], 422);
}

$check = $pdo->prepare('SELECT id FROM users WHERE username = :username OR email = :email LIMIT 1');
$check->execute([
    'username' => $username,
    'email' => $email,
]);
if ($check->fetch()) {
    jsonResponse(false, 'username_exists', null, 409);
}

$inboxCheck = $pdo->prepare('SELECT id FROM inboxes WHERE email_address = :email_address LIMIT 1');
$inboxCheck->execute(['email_address' => $email]);
if ($inboxCheck->fetch()) {
    jsonResponse(false, 'inbox_email_exists', null, 409);
}

$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$ip = getClientIp();
$userAgent = getUserAgent();
$uaDetails = parseUserAgentDetails($userAgent);

$stmt = $pdo->prepare('
    INSERT INTO users (
        name,
        username,
        email,
        password,
        phone,
        avatar,
        country,
        agent,
        ip,
        is_active,
        role,
        created_at,
        updated_at
    ) VALUES (
        :name,
        :username,
        :email,
        :password,
        :phone,
        :avatar,
        :country,
        :agent,
        :ip,
        1,
        :role,
        NOW(),
        NOW()
    )
');

$stmt->execute([
    'name' => $name !== '' ? $name : $username,
    'username' => $username,
    'email' => $email,
    'password' => $hashedPassword,
    'phone' => $phone !== '' ? $phone : null,
    'avatar' => $avatar !== '' ? $avatar : null,
    'country' => $country !== '' ? $country : null,
    'agent' => $userAgent,
    'ip' => $ip,
    'role' => 'user',
]);

$userId = (int) $pdo->lastInsertId();
$userInbox = ensureUserInbox($pdo, $userId, $email);

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

$linkedGuestInbox = null;
if ($guestAccessToken !== '') {
    try {
        if ($guestAction === 'transfer') {
            $linkedGuestInbox = performGuestInboxTransfer($pdo, $userId, $email, $guestAction, $guestAccessToken);
        } else {
            discardGuestInboxByAccessToken($pdo, $guestAccessToken);
        }
        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']) . ' 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' => $userId,
    '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
    WHERE id = :id
');

$updateUser->execute([
    'last_login_ip' => $ip,
    'last_login_agent' => $userAgent,
    'id' => $userId,
]);

$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' => $userId,
    'ip' => $ip,
    'device' => $uaDetails['device'],
    'browser' => $uaDetails['browser'],
    'platform' => $uaDetails['platform'],
    'user_agent' => $userAgent,
    'status' => 'success',
]);

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

jsonResponse(true, 'register_success', [
    'token' => $token,
    'expires_at' => $expiresAt,
    'user' => sanitizeUser($user),
    'username' => $username,
    'email_address' => $email,
    'guest_transfer_action' => $guestAction,
    'guest_transfer_completed' => $linkedGuestInbox !== null,
    'inbox' => $userInbox,
    'linked_guest_inbox' => $linkedGuestInbox,
], 201);
