use std::fmt::Debug;
use std::{env, fs};
use std::env::set_var;
use std::path::PathBuf;
use json::{JsonValue, object};

/// 框架配置
#[derive(Clone, Debug)]
pub struct Config {
    /// 根目录
    pub root_dir: PathBuf,
    /// 配置目录
    pub config_dir: PathBuf,
    /// 启用日志
    pub log: bool,
    /// 启动扩展列表
    pub extend: Vec<String>,
    /// 隐藏插件列表
    pub addon_hide: Vec<String>,
    /// 启动缓存
    pub cache: bool,
    /// 密钥失效时间
    pub token_exp: u64,
    /// 密钥
    pub token: String,
    /// pem路径
    pub pub_key_path: String,
}

impl Config {
    pub fn new(config_dir: PathBuf) -> Result<Config, String> {
        if !config_dir.is_dir() {
            match fs::create_dir_all(&config_dir) {
                Ok(_) => {}
                Err(e) => {
                    return Err(format!("配置文件夹不存在: {}", e));
                }
            }
        }
        // 设置根目录
        let root_dir = config_dir.parent().unwrap().to_path_buf();

        set_var("ROOT_DIR", root_dir.to_str().unwrap());
        set_var("CONFIG_DIR", config_dir.to_str().unwrap());

        let t = config_dir.join("conf.json");
        let json = if !t.is_file() {
            Config::create_json_file(t.clone())?
        } else {
            match fs::read_to_string(t.clone()) {
                Ok(e) => match json::parse(&*e) {
                    Ok(e) => e,
                    Err(_) => Config::create_json_file(t.clone())?
                },
                Err(e) => return Err(format!("文件加载失败: {e}"))
            }
        };
        Ok(Config::form(json))
    }
    fn create_json_file(path_buf: PathBuf) -> Result<JsonValue, String> {
        let data = Config::default().json();
        match fs::write(path_buf.clone(), data.dump().clone()) {
            Ok(_) => {}
            Err(e) => {
                return Err(format!("文件写入失败: {}", e));
            }
        }
        Ok(data)
    }
    fn form(json: JsonValue) -> Self {
        let default = json["default"].as_str().unwrap_or("");
        let json = json["connections"][default].clone();
        let root_dir = PathBuf::from(env::var("ROOT_DIR").unwrap());
        let config_dir = PathBuf::from(env::var("CONFIG_DIR").unwrap());
        Self {
            root_dir,
            config_dir,
            log: json["log"].as_bool().unwrap_or(true),
            extend: json["extend"].members().map(|x| x.to_string()).collect::<Vec<String>>().clone(),
            addon_hide: json["addon_hide"].members().map(|x| x.to_string()).collect::<Vec<String>>().clone(),
            cache: json["cache"].as_bool().unwrap_or(false),
            token_exp: json["token_exp"].as_u64().unwrap_or(60 * 60 * 24),
            token: json["token"].as_str().unwrap_or("").to_string(),
            pub_key_path: json["pub_key_path"].as_str().unwrap_or("").to_string(),
        }
    }
    fn json(self) -> JsonValue {
        let default = "temp".to_string();
        let mut json_data = object! {
            "default":default.clone(),
            "connections":object! {}
        };
        let mut config = object! {};
        config["log"] = self.log.into();
        config["extend"] = self.extend.into();
        config["addon_hide"] = self.addon_hide.into();
        config["token_exp"] = self.token_exp.into();
        config["cache"] = self.cache.into();
        config["token"] = self.token.into();
        config["pub_key_path"] = self.pub_key_path.into();
        json_data["connections"][default] = config.clone();
        json_data
    }
}

impl Default for Config {
    fn default() -> Self {
        Self {
            root_dir: Default::default(),
            config_dir: Default::default(),
            log: false,
            extend: vec![],
            addon_hide: vec![],
            cache: false,
            token_exp: 60 * 60 * 24,
            token: "".to_string(),
            pub_key_path: "".to_string(),
        }
    }
}