use std::{fs, io::Write};

use serde::{Deserialize, Serialize};

#[derive(Clone, Deserialize, Serialize, Debug)]
#[serde(default)]
pub struct Config {
    // 当前服务监听地址，Salvo HTTP 和 socket.io 都挂在这个地址上。
    pub host: String,
    // 玩家客户端连接的 socket.io namespace。
    pub client_ns: String,
    // Socket.IO 的 HTTP 传输路径，前后端和 nginx 需要保持一致。
    pub socket_path: String,
    // 玩家身份校验用的 AES 密钥短语，需和客户端加密逻辑保持一致。
    #[serde(skip_serializing_if = "Option::is_none")]
    pub aes_passphrase: Option<String>,
    // 数据库配置：所有 master/worker 节点都可以直连同一台 DB。
    pub db: Option<DbConfig>,
    // pub post: String,
}

#[derive(Clone, Deserialize, Serialize, Debug)]
#[serde(default)]
pub struct DbConfig {
    // 数据库类型：postgresql、mysql、sqlite。(暂只处理了postgresql)
    pub kind: String,
    // postgresql://admin:123456@localhost:5432/backend_ds
    pub uri: String,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            host: "127.0.0.1:8082".to_string(),
            client_ns: "/ws".to_string(),
            socket_path: "/socket.io".to_string(),
            aes_passphrase: None,
            db: None, //DbConfig::default(),
                      // post: "".to_string(),
        }
    }
}

impl Default for DbConfig {
    fn default() -> Self {
        Self {
            kind: "postgresql".to_string(),
            uri: "postgres://postgres:123456@localhost:5432/backend_ds".to_string(),
        }
    }
}

impl Config {
    pub fn load() -> std::io::Result<Self> {
        let path = "config.json";
        let err_msg = &format!("<{path}>文件不存在或配置异常");
        if !fs::exists(path).expect(err_msg) {
            let mut file = fs::File::create(path).expect(err_msg);
            let json_str = serde_json::to_string_pretty(&Self::default())?;
            file.write_all(json_str.as_bytes())?;
            panic!("请配置config.json相关参数后运行");
        }

        let text = fs::read_to_string(path).expect(err_msg);
        let cfg: Self = serde_json::from_str(&text).expect(err_msg);
        Ok(cfg)
    }
}
