use crate::action::Action;
use crate::{Tools, GLOBAL_DATA};
use crate::PLUGIN_TOOLS;
use json::{array, object, JsonValue};
use std::any::type_name;
#[cfg(any(feature = "mysql", feature = "sqlite", feature = "mssql", feature = "pgsql"))]
use br_db::Db;

/// 模型配置
pub trait Module: Send + Sync + 'static {
    /// =================基础配置=============================
    /// 插件名称
    fn _name(&self) -> &'static str {
        type_name::<Self>().split("::").collect::<Vec<&str>>()[3].to_lowercase().leak()
    }
    /// 模型名称
    /// xxx.xxx
    fn module_name(&self) -> &'static str {
        let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
        format!("{}.{}", t[2], t[3]).leak()
    }
    /// 模型标题
    fn title(&self) -> &'static str;
    /// 模型描述
    fn description(&self) -> &'static str {
        ""
    }
    /// =================视图配置=============================
    /// 模型icon
    fn icon(&self) -> &'static str {
        ""
    }
    /// =================数据库配置=============================
    /// 是否数据表
    fn table(&self) -> bool {
        false
    }
    /// 数据库表名称
    fn _table_name(&self) -> &'static str {
        let mut it = type_name::<Self>().rsplitn(4, "::");
        let _ = it.next().unwrap_or(""); // 最末段
        let t2 = it.next().unwrap_or("");
        let t3 = it.next().unwrap_or("");
        let s = format!("{t3}_{t2}").to_lowercase();
        Box::leak(s.into_boxed_str())
    }
    /// 主键
    fn table_key(&self) -> &'static str {
        "id"
    }
    /// 唯一索引
    fn table_unique(&self) -> &'static [&'static str] {
        &[]
    }
    /// 查询索引
    fn table_index(&self) -> &'static [&'static [&'static str]] {
        &[]
    }
    /// 是否分区
    fn table_partition(&self) -> bool {
        false
    }
    /// 分区配置
    /// *列名
    /// *分区key
    /// *实例 array![str, array![range1, range2, range3...]]
    /// *如果在已有分区的情况下想要修改分区的参照列，先要将当前分区代码删除后刷库，然后写新的分区规则再刷库
    fn table_partition_columns(&self) -> JsonValue {
        array![]
    }
    /// =================功能配置=============================
    /// 加载功能
    /// * name 功能名称
    fn action(&mut self, name: &str) -> Result<Box<dyn Action>, String>;
    /// 模型字段
    fn fields(&mut self) -> JsonValue {
        object! {}
    }
    /// 使用工具
    fn tools(&mut self) -> Tools {
        let tools = PLUGIN_TOOLS.lock().unwrap();
        let tools = tools.get("tools").unwrap().clone();
        tools
    }
    /// 设置全局变量
    fn set_global_data(&mut self, key: &str, value: JsonValue) {
        GLOBAL_DATA.with(|data| {
            data.borrow_mut()[key] = value;
        });
    }
    /// 获取全局变量数据
    fn get_global_data(&mut self) -> JsonValue {
        GLOBAL_DATA.with(|data| {
            data.borrow().clone()
        })
    }
    /// 获取全局变量指定字段数据
    fn get_global_data_key(&mut self, key: &str) -> JsonValue {
        GLOBAL_DATA.with(|data| {
            data.borrow()[key].clone()
        })
    }
    #[cfg(any(feature = "mysql", feature = "sqlite", feature = "mssql", feature = "pgsql"))]
    fn db_table(&mut self) -> Db {
        let table = self._table_name();
        self.tools().db.table(table).clone()
    }
    #[cfg(any(feature = "mysql", feature = "sqlite", feature = "mssql", feature = "pgsql"))]
    fn db_find(&mut self, id: &str) -> JsonValue {
        self.db_table().where_and("id", "=", id.into()).find()
    }
    #[cfg(any(feature = "mysql", feature = "sqlite", feature = "mssql", feature = "pgsql"))]
    fn db_select(&mut self, ids: &str) -> JsonValue {
        self.db_table().where_and("id", "in", ids.into()).select()
    }
    #[cfg(any(feature = "mysql", feature = "sqlite", feature = "mssql", feature = "pgsql"))]
    fn db_insert(&mut self, data: JsonValue) -> String {
        let res = self.db_table().insert(data);
        res.to_string()
    }
    #[cfg(any(feature = "mysql", feature = "sqlite", feature = "mssql", feature = "pgsql"))]
    fn db_delete(&mut self, id: &str) -> usize {
        let delete = self.db_table().where_and("id", "=", id.into()).delete();
        delete.as_usize().unwrap_or(0)
    }
    #[cfg(any(feature = "mysql", feature = "sqlite", feature = "mssql", feature = "pgsql"))]
    fn db_update(&mut self, id: &str, data: JsonValue) -> usize {
        let update = self.db_table().where_and("id", "=", id.into()).update(data);
        update.as_usize().unwrap_or(0)
    }
    /// 监听
    fn handle(&mut self) {}
}
