<?php
/**
 * ajax/sorteio_server.php  (VERSÃO SEGURA COM "TIMER" NO BANCO)
 *
 * POST JSON { sala_id }
 *   - Se ainda não é hora → {status:"aguardando_bola", wait_ms, total_bolas, numeros_sorteados}
 *   - Se é hora → sorteia 1 bola, salva e devolve {status:"ok", numero, total_bolas, numeros_sorteados}
 *
 * POST JSON { sala_id, bingo_feito:true, user_id }
 *   - Fecha sala como bingo_fechado (apenas 1º)
 *
 * Status:
 *   ok
 *   aguardando
 *   aguardando_bola
 *   finalizado
 *   bingo_fechado
 *   erro
 */

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

if (session_status() === PHP_SESSION_NONE) session_start();

require_once '../../../includes/db.php';

// ─── Helper ───────────────────────────────────────────────────────────
function json_exit(array $data, int $code = 200): void {
    http_response_code($code);
    echo json_encode($data, JSON_UNESCAPED_UNICODE);
    exit;
}

function now_dt(): DateTime {
    // Ajuste se seu servidor estiver em outro TZ e você quiser fixar em São Paulo:
    // return new DateTime('now', new DateTimeZone('America/Sao_Paulo'));
    return new DateTime('now');
}

// ─── AUTH ─────────────────────────────────────────────────────────────
if (!isset($_SESSION['usuario_id'])) {
    if (isset($_COOKIE['auth_token']) && $_COOKIE['auth_token'] !== '') {
        $stmt = $pdo->prepare("SELECT id, bet_status FROM bet_usuarios WHERE bet_token = ? LIMIT 1");
        $stmt->execute([$_COOKIE['auth_token']]);
        $u = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($u && (int)$u['bet_status'] === 1) {
            $_SESSION['usuario_id'] = (int)$u['id'];
        }
    }

    if (!isset($_SESSION['usuario_id'])) {
        json_exit(['status' => 'erro', 'message' => 'Não autenticado'], 401);
    }
}

// ─── ENTRADA ─────────────────────────────────────────────────────────
$raw   = file_get_contents('php://input');
$input = json_decode($raw, true);
if (!is_array($input)) $input = [];

$sala_id = (int)($input['sala_id'] ?? 0);
if ($sala_id <= 0) {
    json_exit(['status' => 'erro', 'message' => 'sala_id inválido'], 400);
}

// Velocidade (segura): pega do banco (config ativa) ou usa 1s
$velocidade_sorteio = 1;
try {
    $stc = $pdo->prepare("SELECT velocidade_sorteio FROM configuracoes_jogo WHERE ativo = 1 LIMIT 1");
    $stc->execute();
    $vs = $stc->fetchColumn();
    if ($vs !== false) $velocidade_sorteio = max(1, (int)$vs);
} catch (Throwable $e) {
    $velocidade_sorteio = 1;
}

$user_id = (int)($_SESSION['usuario_id'] ?? 0);

try {
    // ─── LOCK SALA ────────────────────────────────────────────────────
    $pdo->beginTransaction();

    $stmt = $pdo->prepare("SELECT * FROM salas_bingo WHERE id = ? FOR UPDATE");
    $stmt->execute([$sala_id]);
    $sala = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$sala) {
        $pdo->rollBack();
        json_exit(['status' => 'erro', 'message' => 'Sala não encontrada'], 404);
    }

    $status = $sala['status'] ?? '';
    $numeros_sorteados = json_decode($sala['numeros_sorteados'] ?? '[]', true);
    if (!is_array($numeros_sorteados)) $numeros_sorteados = [];

    // ─── SALA NÃO INICIOU ─────────────────────────────────────────────
    if ($status === 'aguardando') {
        $pdo->rollBack();
        json_exit([
            'status' => 'aguardando',
            'total_bolas' => 0,
            'numeros_sorteados' => []
        ]);
    }

    // ─── FINALIZADA / FECHADA ─────────────────────────────────────────
    if ($status === 'finalizado' || $status === 'bingo_fechado') {
        $pdo->rollBack();
        json_exit([
            'status' => $status,
            'total_bolas' => count($numeros_sorteados),
            'numeros_sorteados' => $numeros_sorteados
        ]);
    }

    // ─── TRATAMENTO BINGO_FEITO ───────────────────────────────────────
    if (!empty($input['bingo_feito']) && $input['bingo_feito'] === true) {
        if ($status === 'em_andamento') {
            $pdo->prepare("UPDATE salas_bingo SET status = 'bingo_fechado', fim_jogo = NOW() WHERE id = ?")
                ->execute([$sala_id]);
            $pdo->commit();

            // Log simples
            $logDir = __DIR__ . '/../logs';
            if (!is_dir($logDir)) @mkdir($logDir, 0775, true);
            $who = (int)($input['user_id'] ?? $user_id);
            error_log("[".date('Y-m-d H:i:s')."] BINGO FECHADO — sala #{$sala_id} pelo usuario {$who}\n", 3, $logDir.'/bingo_debug.log');

            json_exit([
                'status' => 'bingo_fechado',
                'total_bolas' => count($numeros_sorteados),
                'numeros_sorteados' => $numeros_sorteados
            ]);
        }

        $pdo->rollBack();
        json_exit([
            'status' => $status,
            'total_bolas' => count($numeros_sorteados),
            'numeros_sorteados' => $numeros_sorteados
        ]);
    }

    // ─── SE JÁ TEM 75 BOLAS → FINALIZA ────────────────────────────────
    if (count($numeros_sorteados) >= 75) {
        $pdo->prepare("UPDATE salas_bingo SET status='finalizado', fim_jogo=NOW() WHERE id=?")
            ->execute([$sala_id]);
        $pdo->commit();

        json_exit([
            'status' => 'finalizado',
            'total_bolas' => 75,
            'numeros_sorteados' => $numeros_sorteados
        ]);
    }

    // ─── TIMER SEGURO (impede acelerar) ───────────────────────────────
    $agora = now_dt();

    // Se proxima_bola_em estiver null, inicializa para AGORA (sorteia já)
    $proximaRaw = $sala['proxima_bola_em'] ?? null;
    $proxima = null;

    if (!empty($proximaRaw)) {
        $proxima = new DateTime($proximaRaw);
    } else {
        // primeira chamada após iniciar: libera agora
        $proxima = clone $agora;
        $pdo->prepare("UPDATE salas_bingo SET proxima_bola_em = ? WHERE id = ?")
            ->execute([$proxima->format('Y-m-d H:i:s'), $sala_id]);
        // não dá commit ainda, seguimos no fluxo
    }

    // Se ainda não chegou a hora, NÃO sorteia
    if ($agora < $proxima) {
        $diffMs = (int)(($proxima->getTimestamp() - $agora->getTimestamp()) * 1000);
        $pdo->commit();

        json_exit([
            'status' => 'aguardando_bola',
            'wait_ms' => max(50, $diffMs),
            'total_bolas' => count($numeros_sorteados),
            'numeros_sorteados' => $numeros_sorteados
        ]);
    }

    // ─── SORTEIA 1 BOLA ───────────────────────────────────────────────
    $todas = range(1, 75);
    $disponiveis = array_values(array_diff($todas, $numeros_sorteados));

    if (empty($disponiveis)) {
        $pdo->prepare("UPDATE salas_bingo SET status='finalizado', fim_jogo=NOW() WHERE id=?")
            ->execute([$sala_id]);
        $pdo->commit();

        json_exit([
            'status' => 'finalizado',
            'total_bolas' => count($numeros_sorteados),
            'numeros_sorteados' => $numeros_sorteados
        ]);
    }

    // random seguro
    $idx = random_int(0, count($disponiveis) - 1);
    $nova_bola = (int)$disponiveis[$idx];

    $numeros_sorteados[] = $nova_bola;

    // Próxima bola só depois de X segundos (config)
    $next = clone $agora;
    $next->modify("+{$velocidade_sorteio} seconds");

    // Persistir: numeros + proxima_bola_em
    $pdo->prepare("UPDATE salas_bingo SET numeros_sorteados = ?, proxima_bola_em = ? WHERE id = ?")
        ->execute([
            json_encode($numeros_sorteados),
            $next->format('Y-m-d H:i:s'),
            $sala_id
        ]);

    $pdo->commit();

    json_exit([
        'status' => 'ok',
        'numero' => $nova_bola,
        'total_bolas' => count($numeros_sorteados),
        'numeros_sorteados' => $numeros_sorteados,
        'next_in_ms' => $velocidade_sorteio * 1000
    ]);

} catch (Throwable $e) {
    if ($pdo->inTransaction()) $pdo->rollBack();
    json_exit(['status' => 'erro', 'message' => 'Erro interno'], 500);
}
