<?php
declare(strict_types=1);

require_once __DIR__ . '/bootstrap.php';
require_once __DIR__ . '/db.php';
require_once __DIR__ . '/user_auth_lib.php';

header('Content-Type: application/json; charset=utf-8');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['ok' => false, 'error' => 'method'], JSON_UNESCAPED_UNICODE);
    exit;
}

mocker_require_csrf_post();

$uid = isset($_SESSION['mocker_user_id']) ? (int) $_SESSION['mocker_user_id'] : 0;
if ($uid <= 0) {
    http_response_code(401);
    echo json_encode(['ok' => false, 'error' => 'auth'], JSON_UNESCAPED_UNICODE);
    exit;
}

$input = json_decode((string) file_get_contents('php://input'), true) ?: [];
$username = trim((string) ($input['username'] ?? ''));
$email = trim((string) ($input['email'] ?? ''));
$password = (string) ($input['password'] ?? '');
$phoneRaw = trim((string) ($input['phone'] ?? ''));
$phone = mocker_normalize_phone($phoneRaw);

if (strlen($username) < 2 || strlen($username) > 64) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'error' => 'username'], JSON_UNESCAPED_UNICODE);
    exit;
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'error' => 'email'], JSON_UNESCAPED_UNICODE);
    exit;
}
if (mocker_is_telegram_pending_email($email)) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'error' => 'email'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($phone === null) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'error' => 'phone'], JSON_UNESCAPED_UNICODE);
    exit;
}
if (strlen($password) < 8) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'error' => 'password'], JSON_UNESCAPED_UNICODE);
    exit;
}

try {
    $pdo = mocker_db();
} catch (Throwable $e) {
    http_response_code(503);
    echo json_encode(['ok' => false, 'error' => 'db'], JSON_UNESCAPED_UNICODE);
    exit;
}

$st = $pdo->prepare(
    'SELECT id, username, email, coins, profile_completed_at FROM users WHERE id = :id LIMIT 1'
);
$st->execute([':id' => $uid]);
$row = $st->fetch(PDO::FETCH_ASSOC);

if (!$row) {
    unset($_SESSION['mocker_user_id']);
    http_response_code(401);
    echo json_encode(['ok' => false, 'error' => 'auth'], JSON_UNESCAPED_UNICODE);
    exit;
}

if (!mocker_user_needs_profile_completion($row)) {
    echo json_encode(
        [
            'ok' => true,
            'alreadyComplete' => true,
            'user' => mocker_user_auth_payload($pdo, $row),
        ],
        JSON_UNESCAPED_UNICODE
    );
    exit;
}

$dup = $pdo->prepare(
    'SELECT id FROM users WHERE (lower(username) = lower(:u) OR lower(email) = lower(:e)) AND id != :id LIMIT 1'
);
$dup->execute([':u' => $username, ':e' => $email, ':id' => $uid]);
if ($dup->fetch()) {
    http_response_code(409);
    echo json_encode(['ok' => false, 'error' => 'taken'], JSON_UNESCAPED_UNICODE);
    exit;
}

$hash = password_hash($password, PASSWORD_DEFAULT);
$now = time();

try {
    $upd = $pdo->prepare(
        'UPDATE users SET username = :u, email = :e, password_hash = :p, phone = :ph, profile_completed_at = :pc WHERE id = :id'
    );
    $upd->execute([
        ':u' => $username,
        ':e' => $email,
        ':p' => $hash,
        ':ph' => $phone,
        ':pc' => $now,
        ':id' => $uid,
    ]);
} catch (PDOException $e) {
    if ($e->getCode() === '23000' || str_contains($e->getMessage(), 'UNIQUE')) {
        http_response_code(409);
        echo json_encode(['ok' => false, 'error' => 'taken'], JSON_UNESCAPED_UNICODE);
        exit;
    }
    http_response_code(500);
    echo json_encode(['ok' => false, 'error' => 'server'], JSON_UNESCAPED_UNICODE);
    exit;
}

$st->execute([':id' => $uid]);
$row = $st->fetch(PDO::FETCH_ASSOC);

echo json_encode(
    [
        'ok' => true,
        'user' => mocker_user_auth_payload($pdo, $row ?: []),
    ],
    JSON_UNESCAPED_UNICODE
);
