Documentation
use crate::database::mysql::SlotsBetRatios;
use crate::des;
use crate::packers::BroadSlotMarquess;
use crate::peer::BonusState;
use crate::robot_service::IRobotService;
use crate::services::LotteryInfo;
use crate::static_def::{get_game_setting, BROADCAST_SERVICE, MASTER_SERVICE};
use anyhow::Result;
use rand::prelude::IteratorRandom;
use rand::Rng;
use std::time::Instant;

/// 机器人状态
#[derive(Default, Debug)]
pub enum RobotState {
    /// 新建
    #[default]
    Start,
    /// 游戏中
    Gaming(usize, usize),
    /// 离开
    Leave,
}

/// 机器人
#[derive(Debug)]
pub struct Robot {
    /// 机器人id
    pub id: i32,
    /// 机器人昵称
    pub nickname: String,
    /// 机器人头像
    pub avatar_id: i32,
    /// vip等级
    pub vip_level: i32,
    /// 机器人押注的倍率
    pub bet_info: SlotsBetRatios,
    /// 机器人玩多久离开
    pub seating_time: u32,
    /// 机器人离开闲置多久
    pub leave_time: u32,
    /// 机器人玩游戏的时候多久旋转一次
    pub spin_time: u32,
    /// 坐下时间
    pub last_seating_time: Instant,
    /// 离开时间
    pub last_leave_time: Instant,
    /// 最后一次旋转时间
    pub last_spin_time_time: Instant,
    /// 当前机器人状态
    pub state: RobotState,
}

impl Robot {
    pub async fn update(
        &mut self,
        rand: &mut rand_chacha::ChaCha20Rng,
        lottery: &[LotteryInfo],
        robot_service: &impl IRobotService,
    ) -> Result<()> {
        match self.state {
            RobotState::Start => {
                if rand.random_range(0..2) == 1 {
                    if let Some((table_id, seat_id)) = robot_service
                        .robot_seat(self.id, self.nickname.clone(), self.avatar_id)
                        .await
                    {
                        self.last_seating_time = Instant::now();
                        self.state = RobotState::Gaming(table_id, seat_id);
                    } else {
                        self.last_leave_time = Instant::now();
                        self.state = RobotState::Leave;
                    }
                } else {
                    self.last_leave_time = Instant::now();
                    self.state = RobotState::Leave;
                }
            }
            RobotState::Gaming(table_id, seat_id) => {
                if self.last_seating_time.elapsed().as_secs() > self.seating_time as u64 {
                    robot_service.robot_remove_seat(table_id, seat_id).await?;
                    self.last_leave_time = Instant::now();
                    self.state = RobotState::Leave;
                } else if self.last_spin_time_time.elapsed().as_secs() > self.spin_time as u64 {
                    self.last_spin_time_time = Instant::now();
                    //随机一个彩金id
                    let lottery_id = lottery
                        .iter()
                        .filter_map(|x| {
                            if x.bet_or_money == 1 {
                                Some(x.lottery_id)
                            } else {
                                None
                            }
                        })
                        .choose(rand);

                    if let Some(lottery_id) = lottery_id {
                        let win = MASTER_SERVICE
                            .robot_lottery_spin(1, lottery_id, self.bet_info.bet_money)
                            .await?;
                        if win > 0 {
                            log::info!("robot_service win lottery:{lottery_id} money:{win}");
                            //中彩金 发送跑马灯
                            let config = get_game_setting();
                            if win as f64 >= config.marquee_money_limit
                                && (win / self.bet_info.bet_money as i64) as u32
                                    > config.marquee_bet_limit
                            {
                                let nickname = self.nickname.clone();
                                let vip_level = self.vip_level;
                                let bonus_state = BonusState::Grand as u8;
                                tokio::spawn(async move {
                                    let send_broad_slot_marquess = async move {
                                        let res = BroadSlotMarquess {
                                            game_id: config.game_id,
                                            nickname: &nickname,
                                            vip_level,
                                            bonus_state,
                                            win,
                                        };
                                        let data = des!(res);
                                        BROADCAST_SERVICE.broadcast_to_all_users(&data).await
                                    };

                                    if let Err(err) = send_broad_slot_marquess.await {
                                        log::error!("send_broad_slot_marquess error:{err}");
                                    }
                                });
                            }
                        }
                    }
                }
            }
            RobotState::Leave => {
                if self.last_leave_time.elapsed().as_secs() >= self.leave_time as u64 {
                    self.id = rand.random_range(10000000..100000000);
                    self.nickname = self.id.to_string();
                    self.avatar_id = rand.random_range(0..10);
                    if let Some((table_id, seat_id)) = robot_service
                        .robot_seat(self.id, self.nickname.clone(), self.avatar_id)
                        .await
                    {
                        self.last_seating_time = Instant::now();
                        self.state = RobotState::Gaming(table_id, seat_id);
                    } else {
                        self.last_leave_time = Instant::now();
                        self.state = RobotState::Leave;
                    }
                }
            }
        }
        Ok(())
    }
}