import {ElMessage} from "element-plus";
import {validateNull} from "/@/utils/validate";
import {listDicUrlArr, listDicUrl} from "/@/api/jsonflow/common";
import {deepClone} from "/@/utils/other";
import {DIC_PROP} from "/@/flow/support/dict-prop";
import {useMessage} from "/@/hooks/message";
/**
 * 远程请求数据字典工具类
 *
 * @author luolin
 * @date 2023-04-25 16:41:52
 */
interface DicDataInterface {
    key: string;
    type?: string;
    typeVal?: string;
    field?: string;
    method?: string;
    dicUrl?: string;
    prefix?: string;
    cascades?: string[];
}

const dicArrUrls = {
    listUsersByUserIds: "/jsonflow/user-role-auditor/list/user-ids",
    listRolesByRoleIds: "/jsonflow/user-role-auditor/list/role-ids",
    listPostsByPostIds: "/jsonflow/user-role-auditor/list/post-ids",
    listDeptsByDeptIds: "/jsonflow/user-role-auditor/list/dept-ids",
    listByFlowInstIds: "/jsonflow/run-flow/list/flow-inst-ids",
    listByOrderIds: "/order/run-application/list/order-ids",
    listByRunNodeIds: "/jsonflow/run-node/list/run-node-ids",
    listByRunJobIds: "/jsonflow/run-job/list/run-job-ids",
}

/**
 * 默认回调映射关系
 */
const dicArrFun = {
    createUser: dicArrUrls.listUsersByUserIds,
    handoverUser: dicArrUrls.listUsersByUserIds,
    receiveUser: dicArrUrls.listUsersByUserIds,
    initiatorId: dicArrUrls.listUsersByUserIds,
    carbonCopy: dicArrUrls.listUsersByUserIds,
    carbonCopyPerson: dicArrUrls.listUsersByUserIds,
    userId: dicArrUrls.listUsersByUserIds,
    delRoleId: dicArrUrls.listUsersByUserIds,
    roleId: dicArrUrls.listUsersByUserIds,
    permission: dicArrUrls.listRolesByRoleIds,
    users: dicArrUrls.listUsersByUserIds,
    roles: dicArrUrls.listRolesByRoleIds,
    posts: dicArrUrls.listPostsByPostIds,
    depts: dicArrUrls.listDeptsByDeptIds,
    handoverUserDept: dicArrUrls.listDeptsByDeptIds,
    receiveDept: dicArrUrls.listDeptsByDeptIds,
    handleUserId: dicArrUrls.listUsersByUserIds,
    parFlowInstId: dicArrUrls.listByFlowInstIds,
    subFlowInstId: dicArrUrls.listByFlowInstIds,
    flowInstId: dicArrUrls.listByFlowInstIds,
    orderId: dicArrUrls.listByOrderIds,
    runNodeId: dicArrUrls.listByRunNodeIds,
    runJobId: dicArrUrls.listByRunJobIds,
    fromRunNodeId: dicArrUrls.listByRunNodeIds,
    toRunNodeId: dicArrUrls.listByRunNodeIds,
}

/**
 * 表格数据加载完成后事件
 */
export const onLoaded = (...keyObjs: DicDataInterface[]) => {
    return async (state: any, keyObjs2?: DicDataInterface) => {
        let dataList = state.dataList;
        if (dataList && dataList.length > 0) {
            try {
                let dicData = {}
                let realKeyObjs = validateNull(keyObjs) ? {} : deepClone(keyObjs)
                if (keyObjs2 && !validateNull(keyObjs2)) realKeyObjs = [deepClone(keyObjs2)]
                for (const keyObj of realKeyObjs) {
                    let {key, type, typeVal, field, dicUrl} = keyObj;
                    if (!field) field = key
                    let keys = keyObjs2 ? dataList : dataList.filter(f => !type || f[type] === typeVal).map(m => m[field])
                        .flat().filter(f => !validateNull(f));
                    let ids = keys.filter((item, index) => {
                        return keys.indexOf(item, 0) === index;
                    });
                    if (validateNull(ids)) {
                        dicData[key] = []
                        continue;
                    }
                    if (!dicUrl) dicUrl = dicArrFun[key];
                    if (dicUrl.indexOf("?") !== -1) {
                        let params = dicUrl.split('?')[1].split('=');
                        dicUrl = dicUrl.replace("{{" + params[0] + "}}", typeVal)
                    }
                    let res = await listDicUrlArr(dicUrl, ids);
                    validateNull(res.data) ? dicData[key] = [] : dicData[key] = res.data;
                }
                Object.assign(state.dicData, dicData);
            } catch (err: any) {
                // 捕获异常并显示错误提示
                ElMessage.error(err.msg || err.data.msg);
            }
        }
    }
};

/**
 * 表单数据加载完成后事件
 */
export const onFormLoadedUrl = (...keyObjs: DicDataInterface[]) => {
    return async (dicData: any, form?: any, keyObjs2?: DicDataInterface) => {
        try {
            let realKeyObjs = validateNull(keyObjs) ? {} : deepClone(keyObjs)
            if (keyObjs2 && !validateNull(keyObjs2)) realKeyObjs = [deepClone(keyObjs2)]
            for (const keyObj of realKeyObjs) {
                let {key, type, typeVal, field, dicUrl} = keyObj;
                if (!field) field = key
                let keys = validateNull(typeVal) ? form[field] : form[type] === typeVal ? form[field] : null;
                if (form instanceof Array) {
                    keys = form.filter(f => !type || f[type] === typeVal).map(m => m[field])
                        .flat().filter(f => !validateNull(f));
                }
                if (!(keys instanceof Array)) keys = keys ? [keys] : []
                let ids = keys.filter((item, index) => {
                    return keys.indexOf(item, 0) === index;
                });
                if (validateNull(ids)) {
                    // 参与者翻译需要
                    dicData[key] = []
                    continue;
                }
                if (!dicUrl) dicUrl = dicArrFun[key];
                let res = await listDicUrlArr(dicUrl, ids);
                validateNull(res.data) ? dicData[key] = [] : dicData[key] = res.data;
            }
        } catch (err: any) {
            // 捕获异常并显示错误提示
            ElMessage.error(err.msg || err.data.msg);
        }
    }
};

const cascadeUrls = {
    listFlowNodeByDefFlowId: "/jsonflow/flow-node/list/def-flow-id/{{key}}",
    listFlowNodeRelByDefFlowId: "/jsonflow/flow-node-rel/list/def-flow-id/{{key}}",
    listNodeJobByFlowNodeId: "/jsonflow/node-job/list/flow-node-id/{{key}}",
    listPreRunNodeByFlowInstId: "/jsonflow/run-node/flow-inst-id/pre/{{key}}?runNodeId={{runNodeId}}",
    listAnyJumpRunNodeByFlowInstId: "/jsonflow/run-node/flow-inst-id/any-jump/{{key}}?runNodeId={{runNodeId}}",
    listRunNodeByFlowInstId: "/jsonflow/run-node/list/flow-inst-id/{{key}}",
    listUsersByRunNodeId: "/jsonflow/run-job/list/users/run-node-id/{{key}}",
    listUserByRunNodeId: "/jsonflow/run-job/list/user/run-node-id/{{key}}",
    listRoleByRunNodeId: "/jsonflow/run-job/list/role/run-node-id/{{key}}",
    listPostByRunNodeId: "/jsonflow/run-job/list/post/run-node-id/{{key}}",
    listDeptByRunNodeId: "/jsonflow/run-job/list/dept/run-node-id/{{key}}",
    listRunJobByRunNodeId: "/jsonflow/run-job/list/run-job/run-node-id/{{key}}",
    listDistRunJobByRunNodeId: "/jsonflow/run-job/list/dist-run-job/run-node-id/{{key}}",
    getRunFlowByCode: "/jsonflow/run-flow/code/{{key}}",
    getRunFlowByFlowInstId: "/jsonflow/run-flow/{{key}}",
    listUserByRoleId: "/jsonflow/user-role-auditor/list-users/{{key}}?jobType={{jobType}}",
}

/**
 * 默认回调映射关系
 */
const dicCascadeFun = {
    flowNodeId: cascadeUrls.listFlowNodeByDefFlowId,
    flowNodeRelId: cascadeUrls.listFlowNodeRelByDefFlowId,
    nodeJobId: cascadeUrls.listNodeJobByFlowNodeId,
    "runReject.toRunNodeId": cascadeUrls.listPreRunNodeByFlowInstId,
    "runJob.toRunNodeId": cascadeUrls.listAnyJumpRunNodeByFlowInstId,
    flowKey: cascadeUrls.getRunFlowByFlowInstId,
    defFlowId: cascadeUrls.getRunFlowByFlowInstId,
    userId: cascadeUrls.listUserByRoleId,
    flowInstId: cascadeUrls.getRunFlowByCode,
    runNodeId: cascadeUrls.listRunNodeByFlowInstId,
    runJobId: cascadeUrls.listRunJobByRunNodeId,
    distRunJobId: cascadeUrls.listDistRunJobByRunNodeId,
    fromRunNodeId: cascadeUrls.listRunNodeByFlowInstId,
    toRunNodeId: cascadeUrls.listRunNodeByFlowInstId,
    handleUserId: cascadeUrls.listUsersByRunNodeId,
    anyJumpUserId: cascadeUrls.listUserByRunNodeId,
    anyJumpRoleId: cascadeUrls.listRoleByRunNodeId,
    anyJumpPostId: cascadeUrls.listPostByRunNodeId,
    anyJumpDeptId: cascadeUrls.listDeptByRunNodeId,
}

/**
 * 表格级联数据事件
 * dynkey 动态表格KEY
 */
export const onCascaded = (...keyObjs: DicDataInterface[]) => {
    return async (state: any, form?: any, dynkey?: any) => {
        let dataList = dynkey? form[dynkey] : state.dataList;
        if (dataList && dataList.length > 0) {
            try {
                let cascadeDic = {}
                for (const keyObj of keyObjs) {
                    let {key, dicUrl, cascades} = keyObj;
                    if (!cascades) continue;
                    for (const cascade of cascades) {
                        let realDicUrl = dicUrl;
                        if (!realDicUrl) realDicUrl = dicCascadeFun[cascade];
                        for (let i = 0; i < dataList.length; i++) {
                            let param = dataList[i][key];
                            if (validateNull(param)) continue;
                            if (!validateNull(cascadeDic[param])) continue
                            // @ts-ignore
                            let url = realDicUrl.replace("{{key}}", param)
                            if (url.indexOf("?") !== -1) {
                                let params = url.split('?')[1].split('=');
                                let p = dataList[i][params[0]];
                                if (validateNull(p)) continue;
                                url = url.replace("{{" + params[0] + "}}", p)
                            }
                            // @ts-ignore
                            let res = await listDicUrl(url);
                            if (validateNull(res.data)) continue;
                            cascadeDic[param] = res.data
                        }
                    }
                }
                Object.assign(state.cascadeDic, cascadeDic);
            } catch (err: any) {
                // 捕获异常并显示错误提示
                ElMessage.error(err.msg || err.data.msg);
            }
        }
    }
};

/**
 * 表单级联数据变更事件
 * index 动态表格index
 */
export const onCascadeChange = (cascadeDic: any, ...keyObjs: DicDataInterface[]) => {
    return async (form: any, keyObjs2?: DicDataInterface, dynkey?: any, index?: number) => {
        try {
            let realKeyObjs = validateNull(keyObjs) ? {} : deepClone(keyObjs)
            if (keyObjs2 && !validateNull(keyObjs2)) realKeyObjs = [deepClone(keyObjs2)]
            for (const keyObj of realKeyObjs) {
                let {key, dicUrl, cascades, prefix} = keyObj;
                if (!cascades) continue;
                for (const cascade of cascades) {
                    let realDicUrl = dicUrl;
                    let reqKey = cascade;
                    if (prefix) reqKey = prefix + "." + cascade;
                    if (!realDicUrl) realDicUrl = dicCascadeFun[reqKey];
                    // @ts-ignore
                    let param = dynkey ? form[dynkey][index][key] : form[key];
                    if (!realDicUrl || validateNull(param)) {
                        if (validateNull(param)) clearCascadeVal(form, keyObjs2, cascade, dynkey, index)
                        continue;
                    }
                    let url = realDicUrl.replace("{{key}}", param)
                    if (url.indexOf("?") !== -1) {
                        let params = url.split('?')[1].split('=');
                        // @ts-ignore
                        let p = dynkey ? form[dynkey][index][params[0]] : form[params[0]];
                        if (validateNull(p)) continue;
                        url = url.replace("{{" + params[0] + "}}", p)
                    }
                    // @ts-ignore
                    let res = await listDicUrl(url);
                    if (validateNull(res.data)) res.data = [];
                    let data = res.data;
                    if (!(data instanceof Array)) data = data ? [data] : []
                    if (typeof(index) !== 'undefined') {
                        cascadeDic[param] = data;
                    } else {
                        cascadeDic[cascade] = data;
                    }
                    clearCascadeVal(form, keyObjs2, cascade, dynkey, index)
                }
            }
        } catch (err: any) {
            // 捕获异常并显示错误提示
            ElMessage.error(err.msg || err.data.msg);
        }
    }
};

function clearCascadeVal(form, keyObjs2, cascade, dynkey, index){
    if (typeof(index) !== 'undefined') {
        if (!validateNull(keyObjs2)) form[dynkey][index][cascade] = null
    } else {
        if (!validateNull(keyObjs2)) form[cascade] = null
    }
}

const dicUrls = {
    flowApplicationGroupName: "/order/flow-application/list/group-name",
    listFlowApplication: "/order/flow-application/list",
    defFlows: "/jsonflow/def-flow/list",
    defFlowGroupName: "/jsonflow/def-flow/list/group-name",
    listRoleName: "/jsonflow/user-role-auditor/list/roles?roleName={{roleName}}",
    listTableName: "/order/create-table/list",
    listUserKey: "/jsonflow/node-job/list/user-key",
    listFlowNodeId: "/jsonflow/flow-node/list",
    listNodeJobId: "/jsonflow/node-job/list",
    runFlows: "/jsonflow/run-flow/list",
    listDept: "/jsonflow/user-role-auditor/list/depts?deptName={{deptName}}",
    listPost: "/jsonflow/user-role-auditor/list/posts?postName={{postName}}",
    listUserKeyVal: "/jsonflow/node-job/list/user-key-val",
    listVarKey: "/jsonflow/flow-node-rel/list/var-key",
    listVarKeyVal: "/jsonflow/flow-node-rel/list/var-key-val",
    listVarVal: "/jsonflow/flow-clazz/list/var-val",
    listUsers: "/jsonflow/user-role-auditor/list/users?userName={{userName}}",
}

/**
 * 默认回调映射关系
 */
const dicUrlFun = {
    groupName: dicUrls.flowApplicationGroupName,
    "defFlow.groupName": dicUrls.defFlowGroupName,
    flowKey: dicUrls.defFlows,
    carbonCopy: dicUrls.listUsers,
    carbonCopyPerson: dicUrls.listUsers,
    tableName: dicUrls.listTableName,
    permission: dicUrls.listRoleName,
    defFlowId: dicUrls.defFlows,
    userKey: dicUrls.listUserKey,
    roleId: dicUrls.listRoleName,
    userId: dicUrls.listUsers,
    handleUserId: dicUrls.listUsers,
    flowNodeId: dicUrls.listFlowNodeId,
    nodeJobId: dicUrls.listNodeJobId,
    initiatorId: dicUrls.listUsers,
    createUser: dicUrls.listUsers,
    code: dicUrls.runFlows,
    flowInstId: dicUrls.runFlows,
    receiveUser: dicUrls.listUsers,
    receiveDept: dicUrls.listDept,
    defFlows: dicUrls.defFlows,
    userKeys: dicUrls.listUserKey,
    userKeyVals: dicUrls.listUserKeyVal,
    varKeyVals: dicUrls.listVarKeyVal,
    varVals: dicUrls.listVarVal,
    roles: dicUrls.listRoleName,
    roles2: dicUrls.listRoleName,
    users: dicUrls.listUsers,
    users2: dicUrls.listUsers,
    delRoleId: dicUrls.listUsers,
    posts: dicUrls.listPost,
    posts2: dicUrls.listPost,
    depts: dicUrls.listDept,
    depts2: dicUrls.listDept,
    formId: dicUrls.listFlowApplication,
}

/**
 * 加载业务字典数据
 */
export const onLoadDicUrl = (...keyObjs: DicDataInterface[]) => {
    return async (dicData: any, form?: any, keyObjs2?: DicDataInterface) => {
        try {
            let realKeyObjs = validateNull(keyObjs) ? {} : deepClone(keyObjs)
            if (keyObjs2 && !validateNull(keyObjs2)) realKeyObjs = [deepClone(keyObjs2)]
            if (!realKeyObjs) return
            for (const keyObj of realKeyObjs) {
                let {key, dicUrl, prefix} = keyObj;
                let res;
                if (dicUrl) res = await listDicUrl(dicUrl);
                else {
                    let reqKey = key;
                    if (prefix) reqKey = prefix + "." + key;
                    let url = dicUrlFun[reqKey]
                    if (url.indexOf("?") !== -1) {
                        if (!validateNull(form)) {
                            let params = url.split('?')[1].split('=');
                            let param = form[params[0]];
                            if (validateNull(param)) continue;
                            url = url.replace("{{" + params[0] + "}}", param)
                        } else {
                            url = url.split('?')[0]
                        }
                    }
                    res = await listDicUrl(url);
                }
                validateNull(res.data) ?  dicData[key] = [] : dicData[key] = res.data;
            }
        } catch (err: any) {
            // 捕获异常并显示错误提示
            ElMessage.error(err.msg || err.data.msg);
        }
    }
};

/**
 * 更新业务字典数据
 */
export const onUpdateDicData = (...keyObjs: DicDataInterface[]) => {
    return async (dicData: any, form: any, formKey?: any) => {
        if (!validateNull(dicData) && !validateNull(form)) {
            try {
                for (const keyObj of keyObjs) {
                    let { key } = keyObj;
                    let newVal = form[key];
                    let dicDataVal = dicData[key];
                    if (validateNull(newVal) || validateNull(dicDataVal)) continue;
                    else {
                        let exist = dicDataVal.filter(f => f[key] === newVal);
                        if (!validateNull(exist)) continue;
                    }
                    let realKey = formKey ? formKey : key;
                    dicData[key].unshift({[realKey]: newVal});
                }
            } catch (err: any) {
                // 捕获异常并显示错误提示
                ElMessage.error(err.msg || err.data.msg);
            }
        }
    }
};

export async function remoteMethodByKey(query, onLoad, dicData, param, key) {
    if (query) {
        let form = {}
        form[param] = query
        await onLoad(dicData, form, {key: key});
    } else {
        dicData[key] = []
    }
}

export function initRemoteMethodAllByKey(onLoad, dicData) {
    return {
        async remoteMethodUser(query: string) {
            await remoteMethodByKey(query, onLoad, dicData, 'userName', "users")
        },
        async remoteMethodRole(query: string) {
            await remoteMethodByKey(query, onLoad, dicData, 'roleName', "roles")
        },
        async remoteMethodPost(query: string) {
            await remoteMethodByKey(query, onLoad, dicData, 'postName', "posts")
        },
        async remoteMethodDept(query: string) {
            await remoteMethodByKey(query, onLoad, dicData, 'deptName', "depts")
        },
        async remoteMethodUser2(query: string) {
            await remoteMethodByKey(query, onLoad, dicData, 'userName', "users2")
        },
        async remoteMethodRole2(query: string) {
            await remoteMethodByKey(query, onLoad, dicData, 'roleName', "roles2")
        },
        async remoteMethodPost2(query: string) {
            await remoteMethodByKey(query, onLoad, dicData, 'postName', "posts2")
        },
        async remoteMethodDept2(query: string) {
            await remoteMethodByKey(query, onLoad, dicData, 'deptName', "depts2")
        }
    }
}

export async function remoteMethodAllByKey(onLoad, dicData, query: string, jobType) {
    if (jobType === DIC_PROP.JOB_USER_TYPE[0].value) {
        await remoteMethodByKey(query, onLoad, dicData, 'userName', "users")
    } else if (jobType === DIC_PROP.JOB_USER_TYPE[1].value) {
        await remoteMethodByKey(query, onLoad, dicData, 'roleName', "roles")
    } else if (jobType === DIC_PROP.JOB_USER_TYPE[2].value) {
        await remoteMethodByKey(query, onLoad, dicData, 'postName', "posts")
    } else if (jobType === DIC_PROP.JOB_USER_TYPE[3].value) {
        await remoteMethodByKey(query, onLoad, dicData, 'deptName', "depts")
    } else useMessage().warning("请先选择参与者类型")
}
