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

// Fortune Slots API – 3 reels x 3 rows, 5 paylines, pool logic like Fortune Wheel

const SLOTS_SYMBOLS = [
    ['id' => 'wild', 'mult' => 5,  'label' => 'WILD', 'weight' => 5],
    ['id' => 'x5',   'mult' => 5,  'label' => '5x',   'weight' => 5],
    ['id' => 'x3',   'mult' => 3,  'label' => '3x',   'weight' => 8],
    ['id' => 'x2',   'mult' => 2,  'label' => '2x',   'weight' => 12],
    ['id' => 'x1',   'mult' => 1,  'label' => '1x',   'weight' => 15],
    ['id' => 'x05',  'mult' => 0.5,'label' => '0.5x', 'weight' => 15],
    ['id' => 'x0',   'mult' => 0,  'label' => '0',    'weight' => 40],
];

// 5 paylines: row0, row1, row2, diag \, diag /
const SLOTS_PAYLINES = [
    [0, 1, 2],     // top row
    [3, 4, 5],     // middle row
    [6, 7, 8],     // bottom row
    [0, 4, 8],     // diagonal \
    [2, 4, 6],     // diagonal /
];

function slots_get_pool_for_update(PDO $pdo): array {
    $stmt = $pdo->prepare('SELECT * FROM slots_pool WHERE id=1 FOR UPDATE');
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$row) {
        $pdo->prepare('INSERT IGNORE INTO slots_pool (id,balance_usd) VALUES (1,0)')->execute();
        $stmt->execute();
        $row = $stmt->fetch(PDO::FETCH_ASSOC) ?: ['id' => 1, 'balance_usd' => 0];
    }
    return $row;
}

function slots_pick_symbol(array $symbols, bool $forceLose = false): array {
    if ($forceLose) {
        foreach ($symbols as $s) {
            if ($s['id'] === 'x0') return $s;
        }
    }
    $total = array_sum(array_column($symbols, 'weight'));
    $r = random_int(1, (int)$total);
    foreach ($symbols as $s) {
        $r -= $s['weight'];
        if ($r <= 0) return $s;
    }
    return $symbols[count($symbols) - 1];
}

function slots_calc_win(array $grid, array $symbolsById): float {
    $best = 0.0;
    foreach (SLOTS_PAYLINES as $line) {
        $ids = [$grid[$line[0]], $grid[$line[1]], $grid[$line[2]]];
        $mults = [];
        $wildCount = 0;
        foreach ($ids as $id) {
            $s = $symbolsById[$id] ?? null;
            if (!$s) continue 2;
            if ($id === 'wild') { $wildCount++; $mults[] = 5.0; }
            else $mults[] = (float)$s['mult'];
        }
        if ($wildCount === 3) { $best = max($best, 5.0); continue; }
        $nonWildMults = [];
        foreach (array_keys($ids) as $i) {
            if ($ids[$i] !== 'wild') $nonWildMults[] = $mults[$i];
        }
        if ($wildCount === 2) { $best = max($best, $nonWildMults[0]); continue; }
        if ($wildCount === 1) {
            $best = max($best, ($nonWildMults[0] === $nonWildMults[1]) ? $nonWildMults[0] : 0);
            continue;
        }
        $best = max($best, ($mults[0] === $mults[1] && $mults[1] === $mults[2]) ? $mults[0] : 0);
    }
    return $best;
}

function slots_spin(): void {
    $user = current_user();
    if (!$user) json_response(['ok' => false, 'error' => 'Login required'], 401);
    if (!empty($user['is_banned'])) json_response(['ok' => false, 'error' => 'Account suspended'], 403);

    $in = json_decode(file_get_contents('php://input'), true) ?: [];
    if (!verify_csrf($in['csrf'] ?? '')) json_response(['ok' => false, 'error' => 'Session expired'], 403);

    $amount = round((float)($in['amount'] ?? 0), 8);
    if ($amount < 0.10) {
        json_response(['ok' => false, 'error' => 'Minimum bet is 0.10 USD']);
    }

    $pdo = db();
    $pdo->beginTransaction();
    try {
        $balStmt = $pdo->prepare('SELECT balance_usd FROM users WHERE id=? FOR UPDATE');
        $balStmt->execute([$user['id']]);
        $bal = (float)$balStmt->fetchColumn();
        if ($amount > $bal) {
            $pdo->rollBack();
            json_response(['ok' => false, 'error' => 'Insufficient balance']);
        }

        $pool = slots_get_pool_for_update($pdo);
        $poolBalBefore = (float)$pool['balance_usd'];

        $pdo->prepare('UPDATE users SET balance_usd = balance_usd - ?, total_bet_usd = total_bet_usd + ? WHERE id=?')
            ->execute([$amount, $amount, $user['id']]);

        $u2 = $pdo->prepare('SELECT balance_usd, display_currency FROM users WHERE id=?');
        $u2->execute([$user['id']]);
        $u = $u2->fetch();
        $pdo->prepare('UPDATE users SET balance_local=? WHERE id=?')
            ->execute([usd_to_local((float)$u['balance_usd'], $u['display_currency']), $user['id']]);

        $pdo->prepare(
            'INSERT INTO transactions (user_id,type,amount_usd,balance_after,description,reference_id,created_at)
             VALUES (?,?,?,?,?,?,NOW())'
        )->execute([
            $user['id'],
            'bet',
            -$amount,
            $u['balance_usd'],
            'Fortune Slots bet',
            'slotsbet_' . time(),
        ]);

        $pdo->prepare('UPDATE slots_pool SET balance_usd = balance_usd + ? WHERE id=1')
            ->execute([$amount]);

        $symbolsById = [];
        foreach (SLOTS_SYMBOLS as $s) {
            $symbolsById[$s['id']] = $s;
        }

        $maxMult = 5.0;
        $maxPayout = $amount * $maxMult;
        $poolAfterBet = $poolBalBefore + $amount;
        $forceLose = $poolAfterBet < $maxPayout;

        $grid = [];
        for ($i = 0; $i < 9; $i++) {
            $sym = slots_pick_symbol(SLOTS_SYMBOLS, $forceLose && $i < 3);
            $grid[] = $sym['id'];
        }

        $mult = slots_calc_win($grid, $symbolsById);
        $payout = $amount * $mult;
        $isWin = $payout > 0;

        if ($isWin) {
            if ($poolAfterBet < $payout) {
                $payout = 0;
                $mult = 0;
                $isWin = false;
            } else {
                $pdo->prepare('UPDATE slots_pool SET balance_usd = balance_usd - ? WHERE id=1')
                    ->execute([$payout]);
                $pdo->prepare('UPDATE users SET balance_usd = balance_usd + ? WHERE id=?')
                    ->execute([$payout, $user['id']]);

                $uq = $pdo->prepare('SELECT balance_usd, display_currency FROM users WHERE id=?');
                $uq->execute([$user['id']]);
                $u = $uq->fetch();
                $pdo->prepare('UPDATE users SET balance_local=? WHERE id=?')
                    ->execute([usd_to_local((float)$u['balance_usd'], $u['display_currency']), $user['id']]);

                $pdo->prepare(
                    'INSERT INTO transactions (user_id,type,amount_usd,balance_after,description,reference_id,created_at)
                     VALUES (?,?,?,?,?,?,NOW())'
                )->execute([
                    $user['id'],
                    'win',
                    $payout,
                    $u['balance_usd'],
                    'Fortune Slots ' . number_format($mult, 1) . 'x win',
                    'slotswin_' . time(),
                ]);
            }
        }

        $reel1 = implode(',', array_slice($grid, 0, 3));
        $reel2 = implode(',', array_slice($grid, 3, 3));
        $reel3 = implode(',', array_slice($grid, 6, 3));

        $pdo->prepare(
            'INSERT INTO slots_games (user_id,bet_usd,reel1,reel2,reel3,multiplier,payout_usd,is_win)
             VALUES (?,?,?,?,?,?,?,?)'
        )->execute([
            $user['id'],
            $amount,
            $reel1,
            $reel2,
            $reel3,
            $mult,
            $payout,
            $isWin ? 1 : 0,
        ]);
        $gid = (int)$pdo->lastInsertId();

        $pdo->commit();

        reduce_wager((int)$user['id'], $amount);
        process_referral_commission((int)$user['id'], $amount, 'bet');

        $balStmt = $pdo->prepare('SELECT balance_usd, display_currency FROM users WHERE id=?');
        $balStmt->execute([$user['id']]);
        $u = $balStmt->fetch();

        json_response([
            'ok' => true,
            'game_id' => $gid,
            'grid' => $grid,
            'multiplier' => $mult,
            'payout_usd' => $payout,
            'is_win' => $isWin,
            'balance_usd' => (float)$u['balance_usd'],
            'fx_rate' => fx_rate($u['display_currency'] ?? 'USD'),
            'symbols' => SLOTS_SYMBOLS,
        ]);
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        json_response(['ok' => false, 'error' => $e->getMessage()], 500);
    }
}

$action = $_GET['action'] ?? '';
switch ($action) {
    case 'spin': slots_spin(); break;
    case 'symbols': json_response(['ok' => true, 'symbols' => SLOTS_SYMBOLS]); break;
    default: json_response(['ok' => false, 'error' => 'Unknown action'], 400);
}
