Documentation
mod db_config;
mod table;

use anyhow::Result;
use sqlx::mysql::MySqlPoolOptions;
use sqlx::MySqlPool;

use crate::config::SingleDB;

pub use db_config::*;
pub use table::*;

/// MYSQL 主库
pub struct Database {
    /// 主库
    game_main: MySqlPool,
}

impl Database {
    /// 新建MYSQL
    pub fn new(config: &SingleDB) -> Result<Self> {
        let game_main = MySqlPoolOptions::new()
            .max_connections(config.mysql_max_connections)
            .connect_lazy(&config.mysql_url)?;
        Ok(Self { game_main })
    }

    /// 获取MYSQL 版本
    #[inline]
    pub async fn version(&self) -> Result<String> {
        let (r,): (String,) = sqlx::query_as("select version()")
            .fetch_one(&self.game_main)
            .await?;
        Ok(r)
    }

    /// 获取游戏配置
    #[inline]
    pub async fn get_game_setting(&self, server_id: u32) -> Result<GameSetting> {
        Ok(
            sqlx::query_as("select * from `game_slots_config` where `service_id`=?")
                .bind(server_id)
                .fetch_one(&self.game_main)
                .await?,
        )
    }

    /// 加载配置值
    #[inline]
    pub async fn load_config_value(&self, key: &str) -> Result<Option<ConfigValue>> {
        Ok(
            sqlx::query_as::<_, ConfigValue>("select * from `config_value` where `key`=?")
                .bind(key)
                .fetch_optional(&self.game_main)
                .await?,
        )
    }

    /// 获取游戏等级配置
    #[inline]
    pub async fn load_slots_levels(&self, game_id: u32) -> Result<Vec<GameSlotsLevel>> {
        Ok(
            sqlx::query_as("select * from `game_slots_levels` where `game_id`=?")
                .bind(game_id)
                .fetch_all(&self.game_main)
                .await?,
        )
    }

    /// 加载老虎机游戏的押注区间
    #[inline]
    pub async fn load_slots_bet_ratios(&self, game_id: u32) -> Result<Vec<SlotsBetRatios>> {
        Ok(sqlx::query_as(
            "select `level_id`,`bet_money`,`bet_line`,`radio` from `slots_bet_ratios` where `game_id`=?",
        )
        .bind(game_id)
        .fetch_all(&self.game_main)
        .await?)
    }

    /// 获取最大vip等级
    #[inline]
    pub async fn get_max_vip_level(&self) -> Result<i32> {
        Ok(
            sqlx::query_as::<_, (Option<i32>,)>("select max(`id`) from `vip_wash_code_cfg`")
                .fetch_one(&self.game_main)
                .await?
                .0
                .map_or(0, |x| x),
        )
    }
    /// 更新玩家数量统计
    #[inline]
    pub async fn update_player_total(
        &self,
        server_id: u32,
        game_id: u32,
        token: i64,
        player: i64,
    ) -> Result<bool> {
        Ok(sqlx::query(
            r#"INSERT INTO `players_total`(`server_id`,`game_id`,`token`,`player`)
        values(?,?,?,?)
        ON DUPLICATE KEY UPDATE `token`=?, `player`=?"#,
        )
        .bind(server_id)
        .bind(game_id)
        .bind(token)
        .bind(player)
        .bind(token)
        .bind(player)
        .execute(&self.game_main)
        .await?
        .rows_affected()
            == 1)
    }

    /// 加载彩金控制模式
    #[inline]
    pub async fn load_lottery_control_mode(&self, service_id: u32) -> Result<i32> {
        Ok(sqlx::query_as::<_, (i32,)>(
            "select `lottery_control_mode` from `game_slots_config` where `service_id`=?",
        )
        .bind(service_id)
        .fetch_optional(&self.game_main)
        .await?
        .map_or(0, |x| x.0))
    }
}