<?php
declare(strict_types=1);
require_once __DIR__ . '/../db.php';

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');
header('X-Content-Type-Options: nosniff');

function api_out(array $data, int $status = 200): void {
    http_response_code($status);
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

$raw  = (string)file_get_contents('php://input');
$body = [];
if ($raw !== '') { $dec = json_decode($raw, true); if (is_array($dec)) $body = $dec; }
if (empty($body)) $body = $_POST;

$action     = trim((string)($body['action'] ?? $_GET['action'] ?? ''));
$apiKey     = trim((string)($body['api_key'] ?? ''));
$apiSecret  = trim((string)($body['api_secret'] ?? ''));
$instanceId = trim((string)($body['instance_id'] ?? ''));

if ($apiKey === '' || $apiSecret === '') {
    api_out(['ok' => false, 'error' => 'Missing api_key or api_secret'], 401);
}

// Authenticate using api_secret_hash column
$pdo = lk_pdo();
try {
    $st = $pdo->prepare("SELECT id, balance, api_secret_hash FROM users WHERE api_key=? AND is_active=1 LIMIT 1");
    $st->execute([$apiKey]);
    $user = $st->fetch(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
    api_out(['ok' => false, 'error' => 'DB error: ' . $e->getMessage()], 500);
}

if (!$user) api_out(['ok' => false, 'error' => 'Invalid api_key'], 401);
if (!hash_equals((string)$user['api_secret_hash'], $apiSecret)) api_out(['ok' => false, 'error' => 'Invalid api_secret'], 401);

$userId = (int)$user['id'];

// ── FETCH ──
if ($action === 'fetch') {
    try {
        $room = $pdo->query("
            SELECT id, room_code, status FROM rooms
            WHERE is_assigned=0 AND status='waiting'
            ORDER BY id ASC LIMIT 1
        ")->fetch(PDO::FETCH_ASSOC);
        if (!$room) api_out(['ok' => false, 'error' => 'No rooms available']);
        api_out(['ok' => true, 'room_code' => $room['room_code'], 'room_id' => (int)$room['id']]);
    } catch (Throwable $e) {
        api_out(['ok' => false, 'error' => 'DB error'], 500);
    }
}

// ── ASSIGN ──
if ($action === 'assign') {
    if ($instanceId === '') api_out(['ok' => false, 'error' => 'instance_id required'], 400);
    try {
        // ── IDEMPOTENCY CHECK ─────────────────────────────────────────────────
        // If this instance_id already has an assigned room, return it immediately
        // instead of consuming another room. Prevents duplicate assignment on
        // retries or race conditions.
        $existChk = $pdo->prepare("SELECT id, room_code FROM rooms WHERE instance_id=? AND (is_assigned=1 OR status='assigned') LIMIT 1");
        $existChk->execute([$instanceId]);
        $existRoom = $existChk->fetch(PDO::FETCH_ASSOC);
        if ($existRoom) {
            api_out([
                'ok'          => true,
                'room_code'   => $existRoom['room_code'],
                'room_id'     => (int)$existRoom['id'],
                'instance_id' => $instanceId,
                'idempotent'  => true,
            ]);
        }
        // ─────────────────────────────────────────────────────────────────────

        $pdo->beginTransaction();
        $room = $pdo->query("
            SELECT id, room_code FROM rooms
            WHERE is_assigned=0 AND status='waiting'
            ORDER BY id ASC LIMIT 1 FOR UPDATE
        ")->fetch(PDO::FETCH_ASSOC);

        if (!$room) { $pdo->rollBack(); api_out(['ok' => false, 'error' => 'No rooms available']); }

        $roomId   = (int)$room['id'];
        $roomCode = trim((string)$room['room_code']);

        $up = $pdo->prepare("
            UPDATE rooms SET
                is_assigned=1, assigned_user_id=?, assigned_at=NOW(),
                expires_at=DATE_ADD(NOW(), INTERVAL 10 MINUTE),
                last_assigned_by='API', assigned_to=?, instance_id=?, status='assigned'
            WHERE id=? AND is_assigned=0 AND status='waiting'
        ");
        $up->execute([$userId, $instanceId, $instanceId, $roomId]);

        if ($up->rowCount() !== 1) { $pdo->rollBack(); api_out(['ok' => false, 'error' => 'Assignment conflict, retry']); }

        $pdo->commit();
        api_out([
            'ok'          => true,
            'room_code'   => $roomCode,
            'room_id'     => $roomId,
            'instance_id' => $instanceId,
            'expires_at'  => date('Y-m-d H:i:s', time() + 600),
        ]);
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        api_out(['ok' => false, 'error' => 'DB error: ' . $e->getMessage()], 500);
    }
}

api_out(['ok' => false, 'error' => 'Unknown action'], 400);
