<?php
require __DIR__.'/_bootstrap.php';

use Zoo\Database;

/*
 * Bot display feed only.
 * It never writes to real `bets`, wallets, deposits, withdrawals or accounting.
 * It is intentionally independent of player login so the startup board can
 * show simulated activity even before a visitor binds/logs in.
 */

function setting(PDO $db,string $key,string $default): string {
    $q=$db->prepare("SELECT setting_value FROM bot_startup_settings WHERE setting_key=?");
    $q->execute([$key]);
    $v=$q->fetchColumn();
    return $v===false?$default:(string)$v;
}
function realPlayers(PDO $db,int $roomId): int {
    $q=$db->prepare("SELECT COUNT(*) FROM room_assignments WHERE room_id=? AND expires_at>NOW()");
    $q->execute([$roomId]);
    return max(0,(int)$q->fetchColumn());
}
function ensureBots(PDO $db,int $roomId,int $need): void {
    $q=$db->prepare("SELECT bot_key FROM bot_startup_presence WHERE room_id=? AND active=1 ORDER BY id");
    $q->execute([$roomId]);
    $active=$q->fetchAll(PDO::FETCH_COLUMN);
    $have=count($active);

    if($have>$need){
        foreach(array_slice(array_reverse($active),0,$have-$need) as $key){
            $db->prepare("UPDATE bot_startup_presence SET active=0,last_seen_at=NOW() WHERE room_id=? AND bot_key=?")
               ->execute([$roomId,$key]);
            $db->prepare("UPDATE bot_simulated_wallets SET active=0,updated_at=NOW() WHERE room_id=? AND bot_key=?")
               ->execute([$roomId,$key]);
        }
    }

    $seedMin=max(5000,(int)setting($db,'seed_min','5000'));
    $seedMax=max($seedMin,(int)setting($db,'seed_max','25000'));

    for($i=$have;$i<$need;$i++){
        $key='B'.strtoupper(bin2hex(random_bytes(5)));
        $name='player'.random_int(100000,999999);
        $seed=(float)random_int($seedMin,$seedMax);

        $db->beginTransaction();
        try{
            $db->prepare("
              INSERT INTO bot_startup_presence
              (room_id,bot_key,display_name,active,activated_at,last_seen_at)
              VALUES (?,?,?,1,NOW(),NOW())
            ")->execute([$roomId,$key,$name]);

            $db->prepare("
              INSERT INTO bot_simulated_wallets
              (room_id,bot_key,simulated_balance,total_seeded,total_bet,total_won,
               active,last_activity_at,created_at,updated_at)
              VALUES (?,?,?, ?,0,0,1,NOW(),NOW(),NOW())
            ")->execute([$roomId,$key,$seed,$seed]);

            $db->prepare("
              INSERT INTO bot_simulated_funding_events
              (room_id,bot_key,event_type,amount,metadata,created_at)
              VALUES (?,?,'bot_seed_credit',?, ?,NOW())
            ")->execute([$roomId,$key,$seed,json_encode([
              'simulated'=>true,'counts_as_revenue'=>false
            ])]);

            $db->commit();
        }catch(Throwable $e){
            if($db->inTransaction())$db->rollBack();
            throw $e;
        }
    }
}

function generate(PDO $db,int $roomId,int $roundId,int $bots,int $uiSeconds): int {
    if($bots<=0)return 0;

    $target=15000*($bots/30);

    $q=$db->prepare("SELECT COALESCE(SUM(amount),0) FROM bot_ui_bets WHERE round_id=?");
    $q->execute([$roundId]);
    $current=(float)$q->fetchColumn();
    $deficit=max(0,$target-$current);
    if($deficit<10)return 0;

    $pollsLeft=max(1,(int)ceil(max(1,$uiSeconds)/0.75));
    $budget=max(150,min($deficit,ceil(($deficit/$pollsLeft)*1.25/50)*50));
    $eventGoal=$bots>=20?min(8,max(3,(int)ceil($budget/300))):min(5,max(1,(int)ceil($budget/300)));

    $q=$db->prepare("
      SELECT p.bot_key,w.simulated_balance
      FROM bot_startup_presence p
      JOIN bot_simulated_wallets w
        ON w.room_id=p.room_id AND w.bot_key=p.bot_key
      WHERE p.room_id=? AND p.active=1 AND w.active=1
      ORDER BY RAND() LIMIT 12
    ");
    $q->execute([$roomId]);
    $rows=$q->fetchAll(PDO::FETCH_ASSOC);
    if(!$rows)return 0;

    $areas=[
      'monkey','rabbit','lion','panda',
      'swallow','pigeon','peacock','eagle',
      'monkey','rabbit','swallow','pigeon',
      'bird_group','beast_group','shark','frog'
    ];

    $made=0;$spent=0;
    for($i=0;$i<$eventGoal && $spent<$budget && $spent<$deficit;$i++){
        $bot=$rows[$i%count($rows)];
        $left=min($budget-$spent,$deficit-$spent);
        if($left<=0)break;

        $stakePool=[50,60,70,80,90,100,120,150,180,200,250,300,350,400,500];
        $per=max(50,$left/max(1,$eventGoal-$i));

        // Random UI-only stake, biased toward useful values near the remaining
        // per-event budget so the configured round-volume target is preserved.
        $maxStake=min($left,max(100,$per*2.25));
        $eligible=array_values(array_filter($stakePool,fn($v)=>$v<=$maxStake));
        if(!$eligible)$eligible=[50];

        $from=(random_int(1,100)<=75)
            ? max(0,(int)floor(count($eligible)/2)-1)
            : 0;
        $amount=(float)$eligible[random_int($from,count($eligible)-1)];

        $cap=(float)min($left,$budget-$spent,$deficit-$spent);
        if($amount>$cap)$amount=floor($cap/10)*10;
        if($amount<10)break;

        if((float)$bot['simulated_balance']<$amount){
            $reseed=15000.0;
            $db->prepare("
              UPDATE bot_simulated_wallets
              SET simulated_balance=simulated_balance+?,
                  total_seeded=total_seeded+?,updated_at=NOW()
              WHERE room_id=? AND bot_key=?
            ")->execute([$reseed,$reseed,$roomId,$bot['bot_key']]);
        }

        $area=$areas[array_rand($areas)];

        $db->beginTransaction();
        try{
            $u=$db->prepare("
              UPDATE bot_simulated_wallets
              SET simulated_balance=simulated_balance-?,
                  total_bet=total_bet+?,
                  last_activity_at=NOW(),updated_at=NOW()
              WHERE room_id=? AND bot_key=? AND simulated_balance>=?
            ");
            $u->execute([$amount,$amount,$roomId,$bot['bot_key'],$amount]);
            if($u->rowCount()!==1){$db->rollBack();continue;}

            $db->prepare("
              INSERT INTO bot_ui_bets
              (round_id,room_id,bot_key,area,amount,created_at)
              VALUES (?,?,?,?,?,NOW(3))
            ")->execute([$roundId,$roomId,$bot['bot_key'],$area,$amount]);

            $db->commit();
            $made++;$spent+=$amount;
        }catch(Throwable $e){
            if($db->inTransaction())$db->rollBack();
            throw $e;
        }
    }
    return $made;
}

try{
    $db=Database::connect();

    // Current active room; startup currently uses room 1 when only one room exists.
    $roomId=max(1,(int)($_GET['room_id']??1));

    $q=$db->prepare("
      SELECT id,public_round_id,state,opened_at,closes_at
      FROM rounds
      WHERE room_id=? AND state='BETTING_OPEN' AND closes_at>NOW(3)
      ORDER BY id DESC LIMIT 1
    ");
    $q->execute([$roomId]);
    $round=$q->fetch(PDO::FETCH_ASSOC);

    if(!$round){
        json_out(['ok'=>true,'betting'=>false,'room_id'=>$roomId,'bot_events'=>[],'last_event_id'=>(int)($_GET['after_id']??0)]);
    }

    $real=realPlayers($db,$roomId);
    $bots=max(0,30-$real);
    ensureBots($db,$roomId,$bots);

    $uiBetting=(string)($_GET['ui_betting']??'')==='1';
    $uiSeconds=max(1,min(60,(int)($_GET['ui_seconds']??15)));
    $generated=$uiBetting?generate($db,$roomId,(int)$round['id'],$bots,$uiSeconds):0;

    $realTotals=[];
    $q=$db->prepare("SELECT area,SUM(amount) total FROM bets WHERE round_id=? GROUP BY area");
    $q->execute([(int)$round['id']]);
    foreach($q->fetchAll(PDO::FETCH_ASSOC) as $r)$realTotals[$r['area']]=(float)$r['total'];

    $botTotals=[];
    $q=$db->prepare("SELECT area,SUM(amount) total FROM bot_ui_bets WHERE round_id=? GROUP BY area");
    $q->execute([(int)$round['id']]);
    foreach($q->fetchAll(PDO::FETCH_ASSOC) as $r)$botTotals[$r['area']]=(float)$r['total'];

    $areas=['monkey','rabbit','lion','panda','swallow','pigeon','peacock','eagle','shark','frog','bird_group','beast_group'];
    $display=[];
    foreach($areas as $a)$display[$a]=round(($realTotals[$a]??0)+($botTotals[$a]??0),2);

    $after=max(0,(int)($_GET['after_id']??0));
    $q=$db->prepare("
      SELECT id,area,amount,created_at
      FROM bot_ui_bets
      WHERE round_id=? AND id>?
      ORDER BY id ASC LIMIT 50
    ");
    $q->execute([(int)$round['id'],$after]);
    $events=$q->fetchAll(PDO::FETCH_ASSOC);

    $last=$after;
    foreach($events as &$e){
        $e['id']=(int)$e['id'];
        $e['amount']=(float)$e['amount'];
        $last=max($last,$e['id']);
    }

    json_out([
      'ok'=>true,
      'betting'=>true,
      'room'=>[
        'id'=>$roomId,
        'visible_players'=>min(30,$real+$bots),
        'players_text'=>'👤 '.min(30,$real+$bots).' Players'
      ],
      'round'=>[
        'id'=>(int)$round['id'],
        'public_round_id'=>$round['public_round_id']
      ],
      'display'=>[
        'candidate_totals'=>$display,
        'total_bet'=>round(array_sum($display),2)
      ],
      'bot_events'=>$events,
      'last_event_id'=>$last,
      'diagnostic'=>[
        'real_players'=>$real,
        'bot_players'=>$bots,
        'generated_this_poll'=>$generated,
        'target_bot_volume'=>round(15000*($bots/30),2),
        'bot_volume'=>round(array_sum($botTotals),2)
      ]
    ]);
}catch(Throwable $e){
    json_out(['ok'=>false,'error'=>$e->getMessage()],500);
}
