use std::collections::HashMap;
use br_db::{Db};
use json::{array, JsonValue, object};
use crate::model::Model;

#[derive(Clone)]
pub struct Tables {
    pub table: String,
    pub header: JsonValue,
    pub request: JsonValue,
    pub db: Db,
    pub search_fields: HashMap<String, Vec<String>>,
    pub query_fields: HashMap<String, Vec<String>>,
    pub hidden_fields: HashMap<String, Vec<String>>,
    pub main_field: HashMap<String, String>,
    pub right_field: HashMap<String, String>,
    pub tables: Vec<(String, JsonValue)>,
    /// 总字段
    pub fields: HashMap<String, Vec<String>>,
    pub columns: JsonValue,
}

impl Tables {
    /// 设置搜索字段
    pub fn set_table(&mut self, table: &str) {
        self.table = table.to_string();
        self.db.table(table);
    }
    /// 设置字段参数
    pub fn set_join_fields(&mut self, mut model: Box<dyn Model>, main_field: &str, right_field: &str, search_fields: Vec<&str>, query_fields: Vec<&str>, hidden_fields: Vec<&str>, show_fields: Vec<&str>) {
        let table = model.table().to_string();
        let fields = model.fields();
        let mut tables_field = object! {};
        let mut field_list = vec![];
        for (name, list) in fields.entries() {
            if show_fields.len() == 0 {
                if !hidden_fields.contains(&&*name.to_string()) {
                    field_list.push(name);
                    tables_field[name] = list.clone();
                }
            } else {
                if show_fields.contains(&&*name.to_string()) {
                    field_list.push(name);
                    tables_field[name] = list.clone();
                }
            }
        }

        self.tables.push((table.clone(), tables_field));
        self.fields.insert(table.clone(), field_list.iter().map(|x| { x.to_string() }).collect::<Vec<String>>());

        self.search_fields.insert(table.clone(), search_fields.iter().map(|x| { x.to_string() }).collect::<Vec<String>>());
        self.query_fields.insert(table.clone(), query_fields.iter().map(|x| { x.to_string() }).collect::<Vec<String>>());
        self.hidden_fields.insert(table.clone(), hidden_fields.iter().map(|x| { x.to_string() }).collect::<Vec<String>>());
        self.main_field.insert(table.clone(), main_field.to_string());
        self.right_field.insert(table.clone(), right_field.to_string());
    }

    pub fn get_columns(&mut self) -> JsonValue {
        let mut data = object! {};
        for (_, fields) in self.tables.clone() {
            for (name, field) in fields.entries() {
                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" | "switch" | "datetime" | "date" | "time" | "year" | "timestamp" => {
                        true.into()
                    }
                    _ => {
                        false.into()
                    }
                };
                if data[name].is_null() {
                    data[name] = row.clone();
                    self.columns.push(row.clone()).unwrap();
                }
            }
        }
        self.columns.clone()
    }
    fn search_title(&mut self) -> String {
        let mut data = vec![];
        for (table, fields) in self.tables.iter_mut() {
            let search_fields = self.search_fields.get(&*table.clone()).unwrap().clone();
            for (name, field) in fields.entries() {
                if search_fields.contains(&name.to_string()) {
                    data.push(field["title"].as_str().unwrap());
                }
            }
        }
        format!("搜索 {}", data.join(" "))
    }
    /// 前端-高级查询条件字段
    fn query_fields(&mut self) -> JsonValue {
        let mut data = array![];
        for (table, fields) in self.tables.iter_mut() {
            let query_fields = self.query_fields.get(&*table.clone()).unwrap().clone();
            for (name, field) in fields.entries() {
                if query_fields.contains(&name.to_string()) {
                    let mut row = field.clone();
                    row["require"] = JsonValue::from(false);
                    data.push(row.clone()).unwrap();
                }
            }
        }
        data
    }
    fn select(&mut self) -> (i32, JsonValue) {
        let page = self.request["page"].as_i32().unwrap();
        let limit = self.request["limit"].as_i32().unwrap();
        let wheres = self.request["where"].clone();
        let order = self.request["order"].clone();
        let filter = self.request["filter"].to_string();

        // 查询到的数据
        let mut data = {
            let mut db = self.db.clone();
            db.table(self.table.as_str());
            for (table, fields) in self.tables.clone() {
                if self.table == table {
                    db.change_table(&*table.to_string().clone());
                } else {
                    db.join(&*table, &*self.main_field.get(&*table).unwrap().clone(), &*self.right_field.get(&*table).unwrap().clone());
                }

                // 整合搜索字段
                if self.search_fields.get(&*table.clone()).unwrap().len() > 0 && filter != "" {
                    let search_fields = self.search_fields.get(&*table.clone()).unwrap().join("|");
                    db.where_and(search_fields.as_str(), "like", format!("%{}%", filter).into());
                }

                // 查询条件
                for item in wheres.members() {
                    let field = item[0].as_str().unwrap_or("");
                    if !fields[field].is_empty() {
                        db.where_and(item[0].as_str().unwrap_or(""), item[1].as_str().unwrap_or(""), item[2].clone());
                    }
                }

                if order.len() > 0 {
                    if self.fields.get(&*table.clone()).unwrap().contains(&order[0].to_string()) {
                        db.order(order[0].as_str().unwrap(), order[1].as_bool().unwrap());
                    }
                }

                if self.fields.get(&*table.clone()).unwrap().len() > 0 {
                    db.field(self.fields.get(&*table.clone()).unwrap().join(",").as_str());
                }
            }
            db.page(page.clone(), limit.clone()).select()
        };
        // 总记录数
        let total = {
            let mut db = self.db.clone();
            db.table(self.table.as_str());
            for (table, fields) in self.tables.clone() {
                if self.table == table {
                    db.change_table(&*table.to_string().clone());
                } else {
                    db.join(&*table, &*self.main_field.get(&*table).unwrap().clone(), &*self.right_field.get(&*table).unwrap().clone());
                }

                if self.search_fields.get(&*table.clone()).unwrap().len() > 0 && filter != "" {
                    let search_fields = self.search_fields.get(&*table.clone()).unwrap().join("|");
                    db.where_and(search_fields.as_str(), "like", format!("%{}%", filter).into());
                }

                for item in wheres.members() {
                    let field = item[0].as_str().unwrap_or("");
                    if !fields[field].is_empty() {
                        db.where_and(item[0].as_str().unwrap_or(""), item[1].as_str().unwrap_or(""), item[2].clone());
                    }
                }
            }
            db.count().as_i32().unwrap_or(0)
        };


        let mut fields_table = false;
        let mut fields_list = object! {};
        for (_, fields) in self.tables.iter_mut() {
            for (_key, field) in fields.entries() {
                fields_list[field["field"].as_str().unwrap()] = field.clone();
                match field["mode"].as_str().unwrap() {
                    "table" => {
                        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 id.contains(",") {
                                item[key] = array![];
                                let ids = id.to_string();
                                let ids = ids.split(",").collect::<Vec<&str>>();
                                for id in ids.iter() {
                                    if fields_table_ids[id.to_string()].is_null() {
                                        let table = field["table"].as_str().unwrap();
                                        let fields_list: Vec<&str> = field["fields"].members().map(|x| x.as_str().unwrap()).collect();
                                        let find = self.db.table(table)
                                            .where_and("id", "=", id.to_string().into())
                                            .field(format!("id,{}", fields_list.join(",")).as_str())
                                            .find();
                                        let mut row = object! {};
                                        if !find.is_empty() {
                                            row["id"] = find["id"].clone();
                                            for field in fields_list.iter() {
                                                if row["value"].is_null() {
                                                    row["value"] = format!("{}", find[field.to_string()]).into();
                                                } else {
                                                    row["value"] = format!("{} | {}", row["value"], find[field.to_string()]).into();
                                                }
                                            }
                                            fields_table_ids[id.to_string()] = row.clone();
                                        } else {
                                            fields_table_ids[id.to_string()] = object! {};
                                        }
                                    }
                                    if !fields_table_ids[id.to_string()].clone().is_empty() {
                                        item[key].push(fields_table_ids[id.to_string()].clone()).unwrap();
                                    }
                                }
                            } else {
                                item[key] = object! {};
                                if fields_table_ids[id.as_str().unwrap()].is_null() {
                                    let table = field["table"].as_str().unwrap();
                                    let fields_list: Vec<&str> = field["fields"].members().map(|x| x.as_str().unwrap()).collect();
                                    let find = self.db.table(table)
                                        .where_and("id", "=", id.clone())
                                        .field(format!("id,{}", fields_list.join(",")).as_str())
                                        .find();


                                    let mut row = object! {};
                                    if !find.is_empty() {
                                        row["id"] = find["id"].clone();
                                        for field in fields_list.iter() {
                                            if row["value"].is_null() {
                                                row["value"] = format!("{}", find[field.to_string()]).into();
                                            } else {
                                                row["value"] = format!("{} | {}", row["value"], find[field.to_string()]).into();
                                            }
                                        }
                                        fields_table_ids[id.as_str().unwrap()] = row;
                                    } else {
                                        fields_table_ids[id.as_str().unwrap()] = object! {};
                                    }
                                }
                                if !fields_table_ids[id.as_str().unwrap()].clone().is_empty() {
                                    item[key] = fields_table_ids[id.as_str().unwrap()].clone();
                                }
                            }
                        }
                        _ => {}
                    }
                }
            }
        }

        (total, data)
    }
    pub fn table_join(&mut self) -> JsonValue {
        let load = self.request["load"].as_str().unwrap();
        let limit = self.request["limit"].as_i32().unwrap();

        let (total, data) = self.clone().select();

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