<?php
declare(strict_types=1);

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

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

$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;
}

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

mocker_user_auth_migrate($pdo);

$load = static function (PDO $pdo, int $userId): ?array {
    $st = $pdo->prepare(
        'SELECT username, twofa_enabled, twofa_secret FROM users WHERE id = :id LIMIT 1'
    );
    $st->execute([':id' => $userId]);
    $row = $st->fetch(PDO::FETCH_ASSOC);
    if (!$row) {
        return null;
    }

    return [
        'username' => (string) ($row['username'] ?? ''),
        'enabled' => (int) ($row['twofa_enabled'] ?? 0) === 1,
        'secret' => trim((string) ($row['twofa_secret'] ?? '')),
    ];
};

$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
if ($method === 'GET') {
    $row = $load($pdo, $uid);
    if (!$row) {
        http_response_code(404);
        echo json_encode(['ok' => false, 'error' => 'not_found'], JSON_UNESCAPED_UNICODE);
        exit;
    }
    echo json_encode([
        'ok' => true,
        'twofa' => [
            'enabled' => $row['enabled'],
        ],
    ], JSON_UNESCAPED_UNICODE);
    exit;
}

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

mocker_require_csrf_post();

$input = json_decode((string) file_get_contents('php://input'), true) ?: [];
$action = (string) ($input['action'] ?? '');
$sessionDraft = $_SESSION['mocker_user_2fa_setup'] ?? null;

if ($action === 'start_setup') {
    $row = $load($pdo, $uid);
    if (!$row) {
        http_response_code(404);
        echo json_encode(['ok' => false, 'error' => 'not_found'], JSON_UNESCAPED_UNICODE);
        exit;
    }
    if ($row['enabled']) {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'twofa_already_enabled'], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $secret = mocker_admin_twofa_generate_secret(20);
    $account = $row['username'] !== '' ? $row['username'] : ('user-' . $uid);
    $uri = mocker_admin_twofa_make_otpauth_uri('Mocker', $account, $secret);
    $_SESSION['mocker_user_2fa_setup'] = [
        'secret' => $secret,
        'createdAt' => time(),
    ];
    echo json_encode([
        'ok' => true,
        'setup' => [
            'secret' => $secret,
            'otpauthUri' => $uri,
            'qrUrl' => 'https://api.qrserver.com/v1/create-qr-code/?size=220x220&data=' . rawurlencode($uri),
        ],
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

if ($action === 'confirm_setup') {
    if (!is_array($sessionDraft) || trim((string) ($sessionDraft['secret'] ?? '')) === '') {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'setup_missing'], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $secret = trim((string) $sessionDraft['secret']);
    $code = trim((string) ($input['code'] ?? ''));
    if (!mocker_admin_twofa_verify_code($secret, $code, 1)) {
        http_response_code(400);
        echo json_encode(['ok' => false, 'error' => 'twofa_invalid'], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $up = $pdo->prepare(
        'UPDATE users SET twofa_enabled = 1, twofa_secret = :secret, twofa_backup_codes_json = :codes WHERE id = :id'
    );
    $up->execute([
        ':secret' => $secret,
        ':codes' => json_encode([], JSON_UNESCAPED_UNICODE),
        ':id' => $uid,
    ]);
    unset($_SESSION['mocker_user_2fa_setup']);
    echo json_encode(['ok' => true], JSON_UNESCAPED_UNICODE);
    exit;
}

http_response_code(400);
echo json_encode(['ok' => false, 'error' => 'action'], JSON_UNESCAPED_UNICODE);
