<?php
ini_set('display_errors', 0);
ini_set('log_errors', 1);
error_reporting(E_ALL);

header('Content-Type: application/json');

set_exception_handler(function($e) {
    http_response_code(500);
    echo json_encode(['ok' => false, 'msg' => 'Server Error: ' . $e->getMessage()]);
    exit;
});

require_once __DIR__ . '/../config.php';

if (session_status() === PHP_SESSION_NONE) session_start();
$is_demo = isset($_SESSION['is_demo']) && $_SESSION['is_demo'] == 1;
if (!$is_demo && isset($_SESSION['user_id'])) {
    $uid_chk = (int)$_SESSION['user_id'];
    $is_demo = (int)$pdo->query("SELECT is_demo FROM users WHERE id = $uid_chk")->fetchColumn();
    if ($is_demo) $_SESSION['is_demo'] = 1;
}
if ($is_demo) {
    echo json_encode(['ok' => false, 'error' => 'This account can only play WinGo.']);
    exit;
}

// Auto-create tables if they don't exist
$pdo->exec("
CREATE TABLE IF NOT EXISTS mines_pool (
    id TINYINT UNSIGNED NOT NULL PRIMARY KEY DEFAULT 1,
    balance DECIMAL(18,2) NOT NULL DEFAULT 0.00,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS mines_games (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    user_id INT(11) NOT NULL,
    bet DECIMAL(18,2) NOT NULL,
    mine_count TINYINT UNSIGNED NOT NULL DEFAULT 3,
    rows_c TINYINT UNSIGNED NOT NULL DEFAULT 5,
    cols_c TINYINT UNSIGNED NOT NULL DEFAULT 5,
    safe_clicks TINYINT UNSIGNED NOT NULL DEFAULT 0,
    clicked_tiles JSON NOT NULL DEFAULT '[]',
    board_mines JSON NOT NULL DEFAULT '[]',
    is_over TINYINT(1) NOT NULL DEFAULT 0,
    is_win TINYINT(1) DEFAULT NULL,
    payout DECIMAL(18,2) NOT NULL DEFAULT 0.00,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    ended_at DATETIME DEFAULT NULL,
    INDEX idx_user (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
");

const MINES_ROWS  = 5;
const MINES_COLS  = 5;
const MINES_MINES = 3;

function json_response($data, $status = 200) {
    http_response_code($status);
    echo json_encode($data);
    exit;
}

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

function get_user($pdo) {
    $user_id = $_SESSION['user_id'] ?? null;
    if (!$user_id) return null;
    $stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
    $stmt->execute([$user_id]);
    return $stmt->fetch(PDO::FETCH_ASSOC);
}

function mines_start() {
    global $pdo;
    $user = get_user($pdo);
    if (!$user) json_response(['ok' => false, 'error' => 'Login required'], 401);

    $in = json_decode(file_get_contents('php://input'), true) ?: [];
    $amount = round((float)($in['amount'] ?? 0), 2);
    
    if ($amount < 10) {
        json_response(['ok' => false, 'error' => 'Minimum bet is Rs 10']);
    }

    $pdo->beginTransaction();
    try {
        $balStmt = $pdo->prepare('SELECT balance 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']);
        }

        // Deduct bet from user balance AND deduct from wager (preventing wager from going below 0)
        $pdo->prepare('UPDATE users SET balance = balance - ?, wager = GREATEST(0, IFNULL(wager, 0) - ?) WHERE id=?')->execute([$amount, $amount, $user['id']]);
        
        // Add to pool
        $pdo->prepare('UPDATE mines_pool SET balance = balance + ? WHERE id=1')->execute([$amount]);

        // Create game (NO MINES PRE-GENERATED!)
        $stmt = $pdo->prepare(
            'INSERT INTO mines_games (`user_id`,`bet`,`mine_count`,`rows_c`,`cols_c`,`safe_clicks`,`clicked_tiles`)
             VALUES (?,?,?,?,?,?,?)'
        );
        $stmt->execute([
            $user['id'],
            $amount,
            MINES_MINES,
            MINES_ROWS,
            MINES_COLS,
            0,
            json_encode([])
        ]);
        $gid = (int)$pdo->lastInsertId();

        $pdo->commit();

        json_response([
            'ok' => true,
            'game_id' => $gid,
            'rows' => MINES_ROWS,
            'cols' => MINES_COLS,
            'mine_count' => MINES_MINES,
            'balance' => $bal - $amount,
        ]);
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        json_response(['ok' => false, 'error' => $e->getMessage()], 500);
    }
}

function generate_fake_mines($clicked_cell, $exclude_cells) {
    $total = MINES_ROWS * MINES_COLS;
    $mines = [$clicked_cell];
    $indices = range(0, $total - 1);
    shuffle($indices);
    foreach($indices as $idx) {
        if (count($mines) >= MINES_MINES) break;
        if (!in_array($idx, $exclude_cells) && $idx !== $clicked_cell) {
            $mines[] = $idx;
        }
    }
    return $mines;
}

function mines_click() {
    global $pdo;
    $user = get_user($pdo);
    if (!$user) json_response(['ok' => false, 'error' => 'Login required'], 401);

    $in = json_decode(file_get_contents('php://input'), true) ?: [];
    $gameId = (int)($in['game_id'] ?? 0);
    $cell   = (int)($in['cell'] ?? -1);
    
    if ($gameId <= 0 || $cell < 0 || $cell >= MINES_ROWS * MINES_COLS) {
        json_response(['ok' => false, 'error' => 'Invalid move']);
    }

    $pdo->beginTransaction();
    try {
        $stmt = $pdo->prepare('SELECT * FROM mines_games WHERE id=? AND user_id=? FOR UPDATE');
        $stmt->execute([$gameId, $user['id']]);
        $g = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if (!$g) {
            $pdo->rollBack();
            json_response(['ok' => false, 'error' => 'Game not found']);
        }
        if ((int)$g['is_over'] === 1) {
            $pdo->rollBack();
            json_response(['ok' => false, 'error' => 'Game already finished']);
        }

        $clicked_tiles = json_decode($g['clicked_tiles'], true) ?: [];
        if (in_array($cell, $clicked_tiles)) {
            $pdo->rollBack();
            json_response(['ok' => false, 'error' => 'Tile already clicked']);
        }

        $safeClicks = (int)$g['safe_clicks'];
        $bet        = (float)$g['bet'];
        
        $new_mult = 1.0 + 0.25 * ($safeClicks + 1);
        $potential_payout = $bet * $new_mult;

        $pool = mines_get_pool_for_update($pdo);
        $pool_bal = (float)$pool['balance'];
        
        $isMine = false;

        // DYNAMIC PROFIT PROTECTION LOGIC
        if ($potential_payout > ($pool_bal * 0.70)) {
            // The pool cannot afford this payout. FORCE A MINE.
            $isMine = true;
        } else {
            // Normal fair probability
            $total_tiles = MINES_ROWS * MINES_COLS;
            $remaining_tiles = $total_tiles - $safeClicks;
            $remaining_mines = MINES_MINES;
            
            $mine_prob = $remaining_mines / $remaining_tiles;
            
            if ((mt_rand() / mt_getrandmax()) <= $mine_prob) {
                $isMine = true;
            }
        }

        $clicked_tiles[] = $cell;
        
        $over   = false;
        $isWin  = false;
        $payout = 0.0;
        $mult   = 1.0 + 0.25 * $safeClicks; // previous mult
        
        $fake_mines = [];

        if ($isMine) {
            $over = true;
            $isWin = false;
            $payout = 0.0;
            $fake_mines = generate_fake_mines($cell, $clicked_tiles);
            $pdo->prepare('UPDATE mines_games SET is_over=1, board_mines=?, ended_at=NOW() WHERE id=?')
                ->execute([json_encode($fake_mines), $gameId]);
        } else {
            $safeClicks++;
            $mult = 1.0 + 0.25 * $safeClicks;
            $pdo->prepare('UPDATE mines_games SET safe_clicks=?, clicked_tiles=? WHERE id=?')
                ->execute([$safeClicks, json_encode($clicked_tiles), $gameId]);
        }

        $pdo->commit();

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

        $out = [
            'ok' => true,
            'game_id' => $gameId,
            'cell' => $cell,
            'is_mine' => $isMine,
            'safe_clicks' => $safeClicks,
            'multiplier' => $mult,
            'is_over' => $over,
            'is_win' => $isWin,
            'payout' => $payout,
            'balance' => (float)$u['balance'],
        ];
        if ($over && $isMine) {
            $out['mines'] = $fake_mines;
        }
        json_response($out);
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        json_response(['ok' => false, 'error' => $e->getMessage()], 500);
    }
}

function mines_cashout() {
    global $pdo;
    $user = get_user($pdo);
    if (!$user) json_response(['ok' => false, 'error' => 'Login required'], 401);

    $in = json_decode(file_get_contents('php://input'), true) ?: [];
    $gameId = (int)($in['game_id'] ?? 0);
    if ($gameId <= 0) json_response(['ok' => false, 'error' => 'Invalid game']);

    $pdo->beginTransaction();
    try {
        $stmt = $pdo->prepare('SELECT * FROM mines_games WHERE id=? AND user_id=? FOR UPDATE');
        $stmt->execute([$gameId, $user['id']]);
        $g = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$g) {
            $pdo->rollBack();
            json_response(['ok' => false, 'error' => 'Game not found']);
        }
        if ((int)$g['is_over'] === 1) {
            $pdo->rollBack();
            json_response(['ok' => false, 'error' => 'Game already finished']);
        }

        $safeClicks = (int)$g['safe_clicks'];
        $bet = (float)$g['bet'];
        if ($safeClicks < 1) {
            $pdo->rollBack();
            json_response(['ok' => false, 'error' => 'Open at least one safe cell first']);
        }

        $mult = 1.0 + 0.25 * $safeClicks;
        $payout = $bet * $mult;

        $pdo->prepare('UPDATE mines_pool SET balance = balance - ? WHERE id=1')->execute([$payout]);
        $pdo->prepare('UPDATE users SET balance = balance + ? WHERE id=?')->execute([$payout, $user['id']]);

        $pdo->prepare('UPDATE mines_games SET is_over=1, is_win=1, payout=?, ended_at=NOW() WHERE id=?')
            ->execute([$payout, $gameId]);

        $pdo->commit();

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

        json_response([
            'ok' => true,
            'game_id' => $gameId,
            'is_over' => true,
            'is_win' => true,
            'multiplier' => $mult,
            'payout' => $payout,
            'balance' => (float)$u['balance'],
        ]);
    } catch (Throwable $e) {
        if ($pdo->inTransaction()) $pdo->rollBack();
        json_response(['ok' => false, 'error' => $e->getMessage()], 500);
    }
}

$action = $_GET['action'] ?? '';
switch ($action) {
    case 'start': mines_start(); break;
    case 'click': mines_click(); break;
    case 'cashout': mines_cashout(); break;
    default: json_response(['ok' => false, 'error' => 'Unknown action'], 400);
}