import { Op, Sequelize } from "sequelize";
import { ERRORENUM } from "../config/errorEnum";
import { mysqlModelMap} from "../db/sqlModelBind";
import { BizError } from "../util/bizError";


/**
 * where条件查询参数
 * @param param 
 * %like%：模糊查询 {列名: {"%like%": }}
 * %gt%：大于 {列名: {"%gt%": }}
 * %gte%：大于等于 {列名: {"%gte%": }}
 * %lt%：小于 {列名: {"%lt%": }}
 * %lte%：小于等于 {列名: {"%lte%": }}
 * %between%：查询范围内数据 {列名: {"%between%": ["开始参数", "结束参数"]}} ---BETWEEN 开始参数 AND 结束参数 列>开始参数 and 列<结束参数
 * %notBetween%：查询不在范围内数据 {列名: {"%notBetween%": ["开始参数", "结束参数"]}} ---NOT BETWEEN 开始参数 AND 结束参数
 * %orderDesc%: order by DESC {"%orderDesc%": "列名"}
 * %limit%: {"%limit%": 数量}
 * @param column 
 * @returns 
 */
function analysisParamToWhere(param, column) {
    let where = {};
    let order = [];
    let group = "";
    let limit = 0;
    for (let key in param) {  
        if (typeof param[key] == "object") {
            where[key] = {};
            for (let whereKey in param[key]){
                switch(whereKey) {
                    case "%like%":
                        where[key][Op.like] = `%${param[key]["%like%"]}%`;
                    break;
                    case "%gt%":
                        where[key][Op.gt] = param[key]["%gt%"];
                    break;
                    case "%gte%":
                        where[key][Op.gte] = param[key]["%gte%"];
                    break;
                    case "%lt%":
                        where[key][Op.lt] = param[key]["%lt%"];
                    break;
                    case "%lte%":
                        where[key][Op.lte] = param[key]["%lte%"];
                    break;
                    case "%between%":
                        where[key][Op.between] = param[key]["%between%"];
                    break;
                    case "%notBetween%":
                        where[key][Op.notBetween] = param[key]["%notBetween%"];
                    break;
                    case "%in%":
                        where[key][Op.in] = param[key]["%in%"];
                    break;
                    case "%notIn%":
                        where[key][Op.notIn] = param[key]["%notIn%"];
                    break;
                    case "%ne%":
                        where[key][Op.ne] = param[key]["%ne%"];
                    break;
                }
            }
        }else {
            switch (key) {
                case "%orderDesc%":
                    order = [[Sequelize.col(param[key]), "DESC"]];
                break;
                case "%orderAsc%":
                    order = [[Sequelize.col(param[key]), "ASC"]];
                break;
                case "%limit%":
                    limit = param[key];
                break;
                case "%group%":
                    group = param[key];
                break;
                default: where[key] = param[key];
            }
        }
    }

    let selectParam:any = {where};
    if (column && column.length) selectParam.attributes = column;
    if (order && order.length) selectParam.order = order;
    if (limit) selectParam.limit = limit;
    if (group) selectParam.group = group;
    return selectParam;
}



/**
 * 查询单个数据
 * @param tableEnumValue 
 * @param param 
 * @param column 
 * @returns 
 */
export async function selectOne(tableEnumValue, param, column) {
    let selectParam = analysisParamToWhere(param, column);
    return await mysqlModelMap[tableEnumValue].findOne(selectParam);
}


/**
 * 查询多个数据
 * @param tableEnumValue 
 * @param param 
 * @param column 
 * @returns 
 */
export async function selectToParam(tableEnumValue, param, column) {
    let selectParam = analysisParamToWhere(param, column);
    return await mysqlModelMap[tableEnumValue].findAll(selectParam);
}


/**
 * 分页查询
 * @param tableEnumValue 
 * @param param 
 * @param column 
 * @param pageNumber 
 * @param pageSize 
 * @returns 
 */
export async function selectToPage(tableEnumValue, param, column, pageNumber:number, pageSize:number) {
    let selectParam:any = analysisParamToWhere(param, column);
    selectParam.limit = pageSize || 10;
    selectParam.offset = (pageNumber-1)*10;
    return await mysqlModelMap[tableEnumValue].findAll(selectParam);
}

/**
 * 查询数量
 * @param tableModel 
 * @param param 
 * @returns 
 */
export async function selectCountByParam(tableEnumValue, param) {
    let selectParam:any = analysisParamToWhere(param, []);
    return await mysqlModelMap[tableEnumValue].count(selectParam);
}



/**
 * 多表联查 列表
 * @param tableEnumValue 
 * @param includeConf {"表名":["",""] } 
 * @param param 
 * @param column 
 * @returns 
 */
export async function selectManyTableToParam(tableEnumValue, includeConf, param, column) {
    let include = [];
    for (let tableName in includeConf) {
        if (!mysqlModelMap[tableName]) throw new BizError(ERRORENUM.不存在表, `尝试进行多表联查，但是不存在${tableName}`);
        let {where, column} = includeConf[tableName];
        let includeInfomation = analysisParamToWhere(where, column);
        includeInfomation.model = mysqlModelMap[tableName];
        include.push(includeInfomation);
    }

    let selectParam:any = analysisParamToWhere(param, column);
    selectParam.include = include;

    return await mysqlModelMap[tableEnumValue].findAll(selectParam);
}



/**
 * 多表联查 分页
 * @param tableEnumValue 
 * @param includeConf {"表名":["",""] } 
 * @param param 
 * @param column 
 * @returns 
 */
export async function selectManyTableToParamToPage(tableEnumValue, includeConf, param, column, pageNumber:number, pageSize:number) {
    let include = [];
    for (let tableName in includeConf) {
        if (!mysqlModelMap[tableName]) throw new BizError(ERRORENUM.不存在表, `尝试进行多表联查，但是不存在${tableName}`);
        let {where, column, required} = includeConf[tableName];
        let includeInfomation = analysisParamToWhere(where, column);
        includeInfomation.model = mysqlModelMap[tableName];
        // if (required != undefined) {
        //     includeInfomation.required = required;
        // }
        include.push(includeInfomation);
    }

    let selectParam:any = analysisParamToWhere(param, column);
    selectParam.include = include;
    selectParam.limit = pageSize || 10;
    selectParam.offset = (pageNumber-1)*10;

    return await mysqlModelMap[tableEnumValue].findAll(selectParam);
}


/**
 * 多表查询单个
 * @param tableModel 
 * @param includeConf 
 * @param param 
 * @param column 
 * @returns 
 */
export async function selectOnceDataForManyTableToParam(tableEnumValue, includeConf, param, column) {
    let include = [];
    for (let tableName in includeConf) {
        if (!mysqlModelMap[tableName]) throw new BizError(ERRORENUM.不存在表, `尝试进行多表联查，但是不存在${tableName}`);
        let {where, column} = includeConf[tableName];
        let includeInfomation = analysisParamToWhere(where, column);
        includeInfomation.model = mysqlModelMap[tableName];
        include.push(includeInfomation);
    }

    let selectParam:any = analysisParamToWhere(param, column);
    selectParam.include = include;

    return await mysqlModelMap[tableEnumValue].findOne(selectParam);
}


