use crate::{
    commons::utils::CONFIG as config,
    db::models::{get_i32, get_string, log::Log},
};
use chrono::{DateTime, Utc};
use serde_json::json;

pub struct Game {
    pub wechat_id: String,
    pub nickname: String,
    pub avatar: String,
    /// 游戏项目(1到6)
    pub item_num: i32,
    /// 排序
    pub game_rank: i32,
    /// 得分
    pub score: i32,
    /// 创建时间
    pub create_date: Option<DateTime<Utc>>,
    pub batch_no: String,
}

impl Game {
    pub async fn exists(wechat_id: &str, item_num: i32, batch_no: &str) -> bool {
        let Some(_) = &config.db else {
            return false;
        };

        let res = crate::db::db_query(
            r#"SELECT COUNT(1) AS record_count
                FROM tb_game
                WHERE wechat_id = ? AND item_num = ? AND batch_no = ?"#,
            vec![json!(wechat_id), json!(item_num), json!(batch_no)],
        )
        .await;

        match res {
            Ok(rows) => rows
                .first()
                .and_then(|row| row.get("record_count"))
                .and_then(|value| value.as_i64().or_else(|| value.as_u64().map(|v| v as i64)))
                .unwrap_or(0)
                > 0,
            Err(_) => false,
        }
    }

    pub async fn insert_once(&self) -> bool {
        if Self::exists(&self.wechat_id, self.item_num, &self.batch_no).await {
            return true;
        }

        self.insert().await
    }

    pub async fn insert(&self) -> bool {
        let Some(_) = &config.db else {
            println!("没有配置数据库, return true;");
            return true;
        };
        let res = crate::db::db_query(
            r#"insert into tb_game(wechat_id,nickname,avatar,item_num,game_rank,score,create_date,batch_no) values(?,?,?,?,?,?,now(),?);"#,
            vec![
                json!(&self.wechat_id),
                json!(&self.nickname),
                json!(&self.avatar),
                json!(&self.item_num),
                json!(&self.game_rank),
                json!(&self.score),
                json!(&self.batch_no),
            ],
        )
        .await;
        match res {
            Ok(res) => {
                // dbg!(&res);
                true
            }
            Err(err) => {
                // dbg!(&err);

                let log = Log {
                    id: 0,
                    msg: err,
                    params: json!({
                        "wechat_id": self.wechat_id,
                        "nickname": self.nickname,
                        "avatar": self.avatar,
                        "item_num": self.item_num,
                        "game_rank":self.game_rank,
                        "score": self.score,
                    }),
                    create_date: None,
                };
                log.insert().await;
                false
            }
        }
    }
    pub async fn get_rank(wechat_id: &str, item_num: i32) -> i32 {
        let Some(_) = &config.db else {
            println!("没有配置数据库, get_rank return 0;");
            return 0;
        };

        let res = crate::db::db_query(
            r#"SELECT COUNT(1) AS rank_count
                FROM tb_game g
                INNER JOIN tb_room r ON r.batch_no = g.batch_no
                WHERE g.wechat_id = ?
                    AND g.item_num = ?
                    AND r.item_num = ?
                    AND g.game_rank BETWEEN 1 AND 10
                    AND DATE(r.create_date) = CURRENT_DATE"#,
            vec![json!(&wechat_id), json!(item_num), json!(item_num)],
        )
        .await;
        match res {
            Ok(res) => res
                .first()
                .and_then(|row| row.get("rank_count"))
                .and_then(|value| value.as_i64().or_else(|| value.as_u64().map(|v| v as i64)))
                .unwrap_or(0) as i32,
            Err(err) => {
                // dbg!(&err);

                // let log = Log {
                //     id: 0,
                //     msg: err,
                //     params: json!({
                //         "wechat_id": self.wechat_id,
                //         "nickname": self.nickname,
                //         "avatar": self.avatar,
                //         "item_num": self.item_num,
                //         "game_rank":self.game_rank,
                //         "score": self.score,
                //     }),
                //     create_date: None,
                // };
                // log.insert().await;
                0
            }
        }
    }
    pub async fn get_top10(batch_no: &str) -> Result<Vec<Self>, String> {
        let Some(_) = &config.db else {
            println!("没有配置数据库, get_top10 return err;");
            return Err("没有配置数据库, get_top10 return err".to_string());
        };

        let res = crate::db::db_query(
            r#"SELECT wechat_id,nickname,avatar,item_num,game_rank,score,batch_no
                FROM tb_game
                WHERE batch_no LIKE ? AND game_rank BETWEEN 1 AND 10
                ORDER BY game_rank ASC"#,
            vec![json!(format!("{}%", batch_no.trim()))],
        )
        .await;
        match res {
            Ok(rows) => rows
                .iter()
                .map(|row| {
                    Ok(Game {
                        wechat_id: get_string(row, "wechat_id")?,
                        nickname: get_string(row, "nickname")?,
                        avatar: get_string(row, "avatar")?,
                        item_num: get_i32(row, "item_num")?,
                        game_rank: get_i32(row, "game_rank")?,
                        score: get_i32(row, "score")?,
                        create_date: None,
                        batch_no: get_string(row, "batch_no")?,
                    })
                })
                .collect(),
            Err(err) => Err(err),
        }
    }
}
