use std::{env, fs};
use std::fs::{create_dir_all, File};
use std::io::Write;
use std::path::{Path, PathBuf};
use br_db::{Mode, Table};
use br_fields::Field;
use json::{array, JsonValue, object};

pub mod test;


use crate::test::Test;
use crate::test::test::table::TestTestTable;
use crate::test::test::TestTest;


use br_cache::Cache;
use br_db::Db;
use br_kafka::Kafka;
use lazy_static::lazy_static;
use std::sync::Mutex;
use std::collections::HashMap;

/// 集合工具
#[derive(Clone)]
pub struct Tools {
    pub db: Db,
    #[cfg(any(feature = "default", feature = "br-cache"))]
    pub cache: Cache,
    #[cfg(any(feature = "default", feature = "br-kafka"))]
    pub kafka: Kafka,
}

lazy_static! {
    /// 工具集合
    pub static ref TOOLS: Mutex<HashMap<String,Tools>> =Mutex::new(HashMap::new());
}



/// 内部插件入口
pub fn plugins(name: &str) -> Box<dyn Plugin> {
    match name {
        _ => Box::new(Test {})
    }
}

/// 内部模型入口
pub fn models(name: &str) -> Box<dyn Model> {
    match name {
        _ => Box::new(TestTest {})
    }
}

/// 内部动作入口
pub fn actions(name: &str) -> Box<dyn Action> {
    match name {
        _ => Box::new(TestTestTable { model: TestTest {} })
    }
}

/// 创建 插件
pub fn plugin_create(path: &str, plugin: &str, plugin_title: &str, model: &str, model_title: &str, action: &str, action_title: &str) {
    let root_path = PathBuf::from(path);
    let plugin_path = root_path.join("plugin");
    let plugin_path = plugin_path.join(plugin);
    create_dir_all(plugin_path.as_os_str()).expect("创建目录失败");

    let plugin_mod_path = plugin_path.join("mod.rs");
    if !plugin_mod_path.is_file() {
        let temp_plugin_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        let temp_plugin_mod_path = temp_plugin_mod_path.join("temp").join("plugin");
        let temp_plugin_mod_data = fs::read_to_string(temp_plugin_mod_path).unwrap();
        let plugin_1 = plugin[0..=0].to_uppercase();
        let plugin_2 = plugin[1..].to_lowercase();
        let temp_plugin_mod_data = temp_plugin_mod_data.replace("{{plugin}}", &*format!("{}{}", plugin_1, plugin_2));
        let temp_plugin_mod_data = temp_plugin_mod_data.replace("{{title}}", plugin_title);
        fs::write(plugin_mod_path, temp_plugin_mod_data).expect("写入插件mod错误");
    }

    if model != "" {
        let model_path = plugin_path.join(model);
        create_dir_all(model_path.as_os_str()).expect("创建模型目录失败");


        let plugin_d = {
            let t: Vec<String> = plugin.split("_").map(|x| {
                let x1 = x[0..=0].to_uppercase();
                let x2 = x[1..].to_lowercase();
                format!("{}{}", x1.clone(), x2.clone())
            }).collect();
            t.join("")
        };
        let model_d = {
            let t: Vec<String> = model.split("_").map(|x| {
                let x1 = x[0..=0].to_uppercase();
                let x2 = x[1..].to_lowercase();
                format!("{}{}", x1.clone(), x2.clone())
            }).collect();
            t.join("")
        };

        let model_mod_path = model_path.join("mod.rs");
        if !model_mod_path.is_file() {
            let temp_plugin_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
            let temp_model_mod_path = temp_plugin_mod_path.join("temp").join("model");
            let mut temp_model_mod_data = fs::read_to_string(temp_model_mod_path).unwrap();
            temp_model_mod_data = temp_model_mod_data.replace("{{model}}", &*format!("{}{}", plugin_d, model_d));
            temp_model_mod_data = temp_model_mod_data.replace("{{plugin_model}}", &*format!("{}_{}", plugin, model));
            let temp_model_mod_data = temp_model_mod_data.replace("{{title}}", model_title);
            fs::write(model_mod_path, temp_model_mod_data).expect("写入模型mod错误");
        }

        if action != "" {
            let action_path = model_path.join(format!("{}.rs", action));
            if !action_path.is_file() {
                let temp_action_mod_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
                let temp_action_mod_path = {
                    match action {
                        "table" => {
                            temp_action_mod_path.join("temp").join("action_table")
                        }
                        "add" => {
                            temp_action_mod_path.join("temp").join("action_add")
                        }
                        "delete" => {
                            temp_action_mod_path.join("temp").join("action_delete")
                        }
                        "put" => {
                            temp_action_mod_path.join("temp").join("action_put")
                        }
                        "select" => {
                            temp_action_mod_path.join("temp").join("action_select")
                        }
                        "get" => {
                            temp_action_mod_path.join("temp").join("action_get")
                        }
                        _ => {
                            temp_action_mod_path.join("temp").join("action")
                        }
                    }
                };

                let temp_action_mod_data = fs::read_to_string(temp_action_mod_path).unwrap();


                let action_d = {
                    let t: Vec<String> = action.split("_").map(|x| {
                        let x1 = x[0..=0].to_uppercase();
                        let x2 = x[1..].to_lowercase();
                        format!("{}{}", x1.clone(), x2.clone())
                    }).collect();
                    t.join("")
                };

                let temp_action_mod_data = temp_action_mod_data.replace("{{action}}", &*format!("{}{}{}", plugin_d, model_d, action_d));
                let temp_action_mod_data = temp_action_mod_data.replace("{{api}}", &*format!("{}.{}.{}", plugin, model, action));
                let temp_action_mod_data = temp_action_mod_data.replace("{{model}}", &*format!("{}{}", plugin_d, model_d));
                let temp_action_mod_data = temp_action_mod_data.replace("{{model_a}}", &*format!("{}", model));
                let temp_action_mod_data = temp_action_mod_data.replace("{{plugin}}", &*format!("{}", plugin));
                let temp_action_mod_data = temp_action_mod_data.replace("{{title}}", action_title);
                fs::write(action_path, temp_action_mod_data).expect("写入动作文件错误");
            }
        }
    }
}


/// 插件
pub trait Plugin {
    fn model(&mut self, name: &str) -> Box<dyn Model>;
    /// 模型名称
    fn title(&mut self) -> &'static str;
    /// 插件描述
    fn describe(&mut self) -> &'static str { return ""; }
}

/// 模型
pub trait Model {
    /// 版本号
    fn version(&mut self) -> &'static str {
        "0.0.1"
    }
    /// 数据库表名称
    fn table(&mut self) -> &'static str;
    /// 模型名称
    fn title(&mut self) -> &'static str;
    /// 模型描述
    fn describe(&mut self) -> &'static str { return ""; }
    /// 字段列表
    fn fields(&mut self) -> JsonValue;

    /// 数据库唯一约束
    fn unique(&mut self) -> Vec<&'static str> {
        return vec![];
    }
    /// 查询索引
    fn index(&mut self) -> Vec<Vec<&'static str>> {
        return vec![];
    }
    /// 主键
    fn primary_key(&mut self) -> &'static str {
        return "id";
    }
    /// 自动ID值
    fn auto(&mut self) -> bool {
        return false;
    }
    /// 创建安装json
    fn json(&mut self) -> Table {
        Table {
            version: self.version().parse().unwrap(),
            table: self.table().parse().unwrap(),
            title: self.title().parse().unwrap(),
            primary_key: self.primary_key().parse().unwrap(),
            auto: self.auto(),
            unique: self.unique().iter().map(|x| x.to_string()).collect(),
            index: self.index().iter().map(|x| x.iter().map(|y| y.to_string()).collect()).collect(),
            fields: self.fields(),
        }
    }
    /// 创建安装文件
    fn create_json_file(&mut self, path: &str) -> bool {
        let json = self.json();
        let o = Path::new(path);
        if !o.is_dir() {
            fs::create_dir(path).unwrap();
        }
        env::set_current_dir(path).unwrap();
        let dir = env::current_dir().unwrap();
        let version = self.version();
        let version = version.replace(".", "_");
        let dir = dir.join(format!("{}_{}.json", self.table(), version));
        let mut f = File::create(dir.to_str().unwrap()).unwrap();
        match f.write_all(json.to_string().as_bytes()) {
            Ok(_) => true,
            Err(_) => false
        }
    }
    /// 模型动作
    fn action(&mut self, name: &str) -> Box<dyn Action>;
    /// 前端搜索字段
    fn table_fields(&mut self) -> JsonValue {
        let mut params = object! {};
        params["load"] = br_fields::select::Radio::new(false, "load", "加载内容", vec!["col", "data"], "data").field();
        params["page"] = br_fields::int::Int::new(false, "page", "页数", 15, 1).field();
        params["limit"] = br_fields::int::Int::new(false, "limit", "记录数", 10, 25).field();
        params["where"] = br_fields::text::Json::new(false, "where", "条件", object! {}).field();
        params["filter"] = br_fields::text::Text::new(false, "filter", "模糊搜索", "").field();
        params["order"] = br_fields::text::Json::new(false, "order", "排序", array![]).field();
        return params;
    }

    fn tools(&mut self) -> Tools {
        let db = TOOLS.lock().unwrap();
        let db = db.get("tools").unwrap().clone();
        db
    }
    /// 前端-数据表
    fn tables(&mut self, _header: JsonValue, request: JsonValue, fields: Vec<&str>, query_fields: Vec<&str>, filter_fields: Vec<&str>) -> JsonValue {
        let load = request["load"].as_str().unwrap();
        let page = request["page"].as_i32().unwrap();
        let limit = request["limit"].as_i32().unwrap();
        let wheres = request["where"].clone();
        let filter = request["filter"].to_string();
        let order = request["order"].clone();
        let columns = self.columns(fields.clone());
        // 查询到的数据
        let mut data = {
            let mut db = self.tools().db;
            let db = db.table(self.table());
            // 整合搜索字段
            if filter_fields.len() > 0 && filter != "" {
                db.where_or(filter_fields.join("|").as_str(), "like", format!("%{}%", filter).into());
            }
            if fields.len() > 0 {
                db.field(fields.join(",").as_str().clone());
            }
            for item in wheres.members() {
                db.where_and(item[0].as_str().unwrap(), item[1].as_str().unwrap(), item[2].clone());
            }
            if order.len() > 0 {
                db.order(order[0].as_str().unwrap(), order[1].as_bool().unwrap());
            }
            db.page(page.clone(), limit.clone()).select()
        };

        // 总记录数
        let total = {
            let mut db = self.tools().db;
            let db = db.table(self.table());
            if filter_fields.len() > 0 && filter != "" {
                db.where_or(filter_fields.join("|").as_str(), "like", format!("%{}%", filter).into());
            }
            for item in wheres.members() {
                db.where_and(item[0].as_str().unwrap(), item[1].as_str().unwrap(), item[2].clone());
            }
            db.count().as_i32().unwrap()
        };


        let mut fields_table = false;
        let mut fields_list = object! {};
        for field in columns.members() {
            fields_list[field["field"].as_str().unwrap()] = field.clone();
            match field["mode"].as_str().unwrap() {
                "table" | "file" => {
                    fields_table = true;
                }
                _ => {}
            }
        }
        if fields_table {
            let mut fields_table_ids = object! {};
            for item in data.members_mut() {
                for (key, field) in fields_list.entries() {
                    match field["mode"].as_str().unwrap() {
                        "table" => {
                            let id = item[key].clone();
                            if id.is_empty() {
                                continue;
                            }
                            if fields_table_ids[id.as_str().unwrap()].is_null() {
                                let table = field["table"].as_str().unwrap();
                                let field: Vec<&str> = field["fields"].members().map(|x| x.as_str().unwrap()).collect();
                                let find = self.tools().db.table(table)
                                    .where_and("id", "=", id.clone())
                                    .field(format!("id,{}", field.join(",")).as_str().clone())
                                    .find();
                                let mut row = object! {};
                                if !find.is_empty() {
                                    row["id"] = find["id"].clone();
                                    for field in field.iter() {
                                        if row["value"].is_null() {
                                            row["value"] = format!("{}", find[field.clone()]).into();
                                        } else {
                                            row["value"] = format!("{} | {}", row["value"], find[field.clone()]).into();
                                        }
                                    }
                                    fields_table_ids[id.as_str().unwrap()] = row;
                                } else {
                                    fields_table_ids[id.as_str().unwrap()] = object! {};
                                }
                            }
                            item[key] = fields_table_ids[id.as_str().unwrap()].clone();
                        }
                        "file" => {
                            let id = item[key].clone();
                            if id.is_empty() {
                                item[key] = array![];
                                continue;
                            }
                            let files = self.tools().db.table("file_file")
                                .where_and("id", "in", id.clone())
                                .field("id,mode,url,type,encrypt")
                                .select();
                            item[key] = files;
                        }
                        _ => {}
                    }
                }
            }
        }

        let mut table = object! {};
        table["total_page"] = JsonValue::from((total as f64 / limit as f64).ceil() as i64);
        table["total_data"] = total.into();
        table["data"] = data.clone();
        match load {
            "col" => {
                table["col"] = columns.clone();
                table["query_fields"] = self.query_fields(query_fields.clone());
                table["filter_title"] = self.filter_title(filter_fields.clone()).into();
            }
            _ => {}
        }
        table
    }

    /// 前端-列数据
    fn columns(&mut self, fields: Vec<&str>) -> JsonValue {
        let columns = self.fields();
        let mut data = array![];
        for (key, field) in columns.entries() {
            if fields.contains(&key) || fields.len() == 0 {
                let mut row = field.clone();
                row["name"] = field["field"].clone();
                row["label"] = field["title"].clone();
                row["align"] = "center".into();
                row["sortable"] = match field["mode"].as_str().unwrap() {
                    "int" | "float" => {
                        true.into()
                    }
                    _ => {
                        false.into()
                    }
                };
                data.push(row.clone()).unwrap();
            }
        }
        data
    }
    /// 前端-高级查询条件字段
    fn query_fields(&mut self, fields: Vec<&str>) -> JsonValue {
        let columns = self.fields();
        let mut data = array![];
        for (key, field) in columns.entries() {
            if fields.contains(&key) {
                let mut row = field.clone();
                row["require"] = JsonValue::from(false);
                data.push(row.clone()).unwrap();
            }
        }
        data
    }
    /// 前端-模糊查询标题
    fn filter_title(&mut self, fields: Vec<&str>) -> String {
        let columns = self.fields();
        let mut data = vec![];
        for (key, field) in columns.entries() {
            if fields.contains(&key) {
                data.push(field["title"].as_str().unwrap());
            }
        }
        format!("搜索 {}", data.join(" "))
    }

    /// 前端-按钮数据
    fn btn_data(&mut self, title: &str, mut action: Box<dyn Action>, mode: BtnMode, color: BtnColor, match_condition: Vec<Vec<&str>>) -> JsonValue {
        let mut btn = object! {};
        if title.is_empty() {
            btn["title"] = action.title().into();
        } else {
            btn["title"] = title.into();
        }
        btn["api"] = action.name().into();
        let mut params = array![];
        for (_, item) in action.params().entries() {
            params.push(item.clone()).unwrap();
        }
        btn["params"] = JsonValue::from(params);
        btn["color"] = JsonValue::from(color.from());
        btn["mode"] = JsonValue::from(mode.from());
        btn["match_condition"] = match_condition.into();
        return btn;
    }


    /// 前端-按钮-指定页面
    fn btn_path_data(&mut self, title: &str, path: &str, color: BtnColor, match_condition: Vec<Vec<&str>>) -> JsonValue {
        let mut btn = object! {};
        btn["title"] = title.into();
        btn["path"] = JsonValue::from(path);
        btn["color"] = JsonValue::from(color.from());
        btn["mode"] = JsonValue::from("path");
        btn["match_condition"] = match_condition.into();
        return btn;
    }

    /// 前端 关联搜索字段
    fn table_select_fields(&mut self) -> JsonValue {
        let mut fields = object! {};
        fields[self.primary_key()] = br_fields::str::Key::new(true, self.primary_key(), "ID", 20).field();
        fields["filter"] = br_fields::text::Text::new(true, "filter", "模糊搜索", "").field();
        return fields;
    }
    /// 前端-select
    fn table_select(&mut self, request: JsonValue, fields: Vec<&str>, filter: Vec<Vec<&str>>) -> JsonValue {
        let id = request["id"].as_str().unwrap();
        let wheres = request["filter"].as_str().unwrap();

        let mut db = self.tools().db;
        let db = db.table(self.table());

        db.field(format!("id,{}", fields.join(",")).as_str().clone());

        for item in filter.iter() {
            db.where_and(item[0], item[1], item[2].into());
        }
        if wheres != "" {
            if id != "" {
                db.where_or("id", "=", id.into());
            }
            db.where_or(fields.join("|").as_str(), "like", format!("%{}%", wheres).into());
        } else {
            if id != "" {
                db.where_or("id", "=", id.into()).where_or("id", "!=", id.into());
            }
        }

        let data = db.select();
        let mut list = array![];
        for item in data.members() {
            let mut row = object! {};
            row["id"] = item["id"].clone();
            for field in fields.iter() {
                if row["value"].is_null() {
                    row["value"] = format!("{}", item[field.clone()]).into();
                } else {
                    row["value"] = format!("{} | {}", row["value"], item[field.clone()]).into();
                }
            }
            list.push(row).unwrap();
        }
        list
    }
}

/// 按钮颜色
pub enum BtnColor {
    Red,
    Blue,
    Yellow,
}

impl BtnColor {
    fn from(self) -> &'static str {
        match self {
            BtnColor::Red => "red",
            BtnColor::Blue => "blue",
            BtnColor::Yellow => "yellow",
        }
    }
}

/// 按钮模式
pub enum BtnMode {
    Form,
    Url,
    Api,
    Download,
    Path,
}

impl BtnMode {
    fn from(self) -> &'static str {
        match self {
            BtnMode::Form => "form",
            BtnMode::Url => "url",
            BtnMode::Api => "api",
            BtnMode::Download => "download",
            BtnMode::Path => "path",
        }
    }
}

/// 动作
pub trait Action {
    /// 标题
    fn title(&mut self) -> &'static str;
    /// api名称
    fn name(&mut self) -> &'static str;
    /// 是否使用密钥
    fn token(&mut self) -> bool { true }
    /// API描述
    fn describe(&mut self) -> &'static str { return ""; }
    /// 是否公开
    fn public(&mut self) -> bool { true }
    /// 接口类型 btn menu
    fn interface_type(&mut self) -> &'static str {
        ""
    }
    /// 依赖接口
    fn dependent(&mut self) -> Vec<&'static str> {
        return vec![];
    }
    /// 请求参数入口
    fn params(&mut self) -> JsonValue { object! {} }
    /// 检测
    fn _check(&mut self, mut request: JsonValue) -> (bool, String, JsonValue) {
        let params = self.params();
        let mut new_request = object! {};
        for (key, field) in params.entries() {
            if request[key].is_null() && field["require"].as_bool().unwrap() {
                return (false, format!("缺少参数 {}:{}", key, field["title"]), request);
            }
            if request[key].is_empty() && field["require"].as_bool().unwrap() {
                request[key] = field["def"].clone().into();
            }
            if request[key].is_null() && !field["require"].as_bool().unwrap() {
                request[key] = field["def"].clone().into();
            }
            if request[key] == JsonValue::from("null") {
                request[key] = field["def"].clone().into();
            }
            new_request[key] = request[key].clone();
        }
        return (true, "验证通过".to_string(), new_request);
    }
    /// 执行参数入口
    fn run(&mut self, header: JsonValue, request: JsonValue) -> Response {
        let (state, msg, request) = self._check(request.clone());
        if !state {
            return self.fail(&*msg);
        }
        return self.index(header.clone(), request.clone());
    }
    fn index(&mut self, header: JsonValue, request: JsonValue) -> Response;
    fn success(&mut self, data: JsonValue, msg: &str) -> Response {
        Response::success(data, msg)
    }
    fn fail(&mut self, msg: &str) -> Response {
        Response::fail(msg)
    }
    fn login(&mut self, msg: &str) -> Response {
        Response::login(msg)
    }
    fn download(&mut self, filename: &str) -> Response {
        Response::download(filename)
    }
    fn redirect(&mut self, url: &str) -> Response {
        Response::redirect(url)
    }
    /// 获取工具集合
    fn tools(&mut self) -> Tools {
        TOOLS.lock().unwrap().get("tools").unwrap().clone()
    }
}


#[derive(Clone, Debug)]
pub struct Response(i32, &'static str, JsonValue);

impl Response {
    /// 获取状态
    pub fn get_code(self) -> i32 {
        self.0
    }
    /// 获取消息
    pub fn get_msg(self) -> &'static str {
        self.1
    }
    /// 获取数据
    pub fn get_data(self) -> JsonValue {
        self.2
    }
    pub fn into(self) -> (i32, &'static str, JsonValue) {
        return (self.0, self.1, self.2);
    }
    /// 成功
    pub fn success(data: JsonValue, msg: &str) -> Self {
        let data = object! {code: 0,data:data,msg: msg.to_string()};
        Self(200, "json", data)
    }
    /// 失败
    pub fn fail(msg: &str) -> Self {
        let data = object! {
            code: -1,
            msg: msg.to_string()
        };
        Self(200, "json", data)
    }
    /// 登陆
    pub fn login(msg: &str) -> Self {
        let data = object! {code: 1000,msg: msg.to_string(),};
        Self(200, "json", data)
    }
    /// 下载
    pub fn download(filename: &str) -> Self {
        Self(200, "download", filename.into())
    }
    /// 重定向
    pub fn redirect(url: &str) -> Self {
        Self(301, "url", url.into())
    }
}

pub struct ApiModel {}

impl ApiModel {
    pub fn run(args_new: Vec<String>) -> (bool, String, String, String, String, JsonValue) {
        let mut args: Vec<String> = env::args().collect();
        if args_new.len() > 0 {
            args = args_new.clone();
        }
        if args.len() <= 1 {
            return (false, "参数错误".to_string(), "".to_string(), "".to_string(), "".to_string(), object! {});
        }
        let mode = args[1].as_str();
        let api = args[2].as_str();
        if api.is_empty() {
            return (false, "无API参数".to_string(), "".to_string(), "".to_string(), "".to_string(), object! {});
        }
        let api: Vec<&str> = api.split(".").collect();
        if api.len() != 3 {
            return (false, "API参数错误".to_string(), "".to_string(), "".to_string(), "".to_string(), object! {});
        }
        let data = args[3].as_str();
        if data.is_empty() {
            return (false, "请求参数无效".to_string(), "".to_string(), "".to_string(), "".to_string(), object! {});
        }
        let data = json::parse(data).unwrap();
        return (true, mode.to_string(), api[0].to_string(), api[1].to_string(), api[2].to_string(), data);
    }
    pub fn fail(msg: &str) -> JsonValue {
        let data = object! {code:-1,msg:msg};
        return data;
    }
}


