<template>
    <div :style="props.currFlowForm ? 'width: 70%; margin-left: 15%' : ''">
        <el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="120px" v-loading="loading"
                 :disabled="operType === 'view'">
            <el-row :gutter="24">

                <el-col :span="12" class="mb20">
                    <el-form-item :label="t('formoption.type')" prop="type">
                        <el-select v-model="form.type" :placeholder="t('formoption.inputTypeTip')" clearable filterable
                                   @change="typeChange" :disabled="true">
                            <el-option v-for="(item, index) in DIC_PROP.FORM_DATA_TYPE" :key="index" :label="item.label"
                                       :value="item.value"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="12" class="mb20">
                    <el-form-item :label="t('formoption.formType')" prop="formType">
                        <el-select v-model="form.formType" :placeholder="t('formoption.inputFormTypeTip')" clearable
                                   filterable
                                   @change="formTypeChange" :disabled="disabledFields.formType">
                            <el-option v-for="(item, index) in DIC_PROP.FORM_TYPE" :key="index" :label="item.label"
                                       :value="item.value"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>

                <el-col :span="12" class="mb20" v-if="!props.currFlowForm">
                    <el-form-item :label="t('formoption.formId')" prop="formId">
                        <el-select v-model="form.formId" :placeholder="t('formoption.inputFormIdTip')" clearable
                                   filterable
                                   @change="formIdChange">
                            <el-option v-for="(item, index) in dicData.formIdByType" :key="index"
                                       :label="item.formName" :value="item.id"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>

                <el-col :span="12" class="mb20" v-if="!hiddenFields.defFlowId">
                    <el-form-item :label="t('formoption.defFlowId')" prop="defFlowId">
                        <el-select v-model="form.defFlowId" :placeholder="t('formoption.inputDefFlowIdTip')" clearable
                                   filterable
                                   @change="cascadeChange('defFlowId', ['flowNodeId'])">
                            <el-option v-for="(item, index) in dicData.defFlowId" :key="index" :label="item.flowName"
                                       :value="item.id"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="12" class="mb20" v-if="!hiddenFields.flowNodeId">
                    <el-form-item :label="t('formoption.flowNodeId')" prop="flowNodeId">
                        <el-select v-model="form.flowNodeId" :placeholder="t('formoption.inputFlowNodeIdTip')" clearable
                                   filterable
                                   @change="changeFlowNodeId">
                            <el-option v-for="(item, index) in cascadeDic.flowNodeId" :key="index"
                                       :label="item.nodeName" :value="item.id"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>

                <el-col :span="12" class="mb20" v-if="!hiddenFields.flowNodeId">
                    <el-form-item :label="t('formoption.resetBtn')" prop="resetBtn">
                        <el-button icon="RefreshLeft" size="small" type="primary" circle
                                   @click="resetFormPerm"></el-button>
                    </el-form-item>
                </el-col>

                <el-col :span="12" class="mb20" v-if="!hiddenFields.printInfo">
                    <el-form-item :label="t('formoption.printInfo')" prop="printInfo">
                        <el-input v-model="form.printInfo" :placeholder="t('formoption.inputPrintInfoTip')"/>
                    </el-form-item>
                </el-col>

                <el-col :span="24" class="mb20">
                    <el-form-item :label="t('createTable.columnInfo')" prop="columns">
                        <el-table :data="form.columns" border style="width: 100%" max-height="500">
                            <el-table-column type="index" :label="t('createTable.index')" width="80">
                                <template #header>
                                    <el-button icon="Plus" size="small" type="primary" circle @click="onAddItem"
                                               :disabled="disabledFields.label"></el-button>
                                </template>
                                <template #default="scope">
                                    <el-button icon="Minus" size="small" type="danger" circle
                                               @click="handleDelete(scope.$index, scope.row)"></el-button>
                                </template>
                            </el-table-column>
                            <el-table-column prop="propId" :label="t('formoption.propId')" show-overflow-tooltip
                                             v-if="!hiddenFields.propId && !props.currFlowForm">
                                <template #default="scope">
                                    <el-input v-model="scope.row.propId" :placeholder="t('formoption.inputPropIdTip')"/>
                                </template>
                            </el-table-column>
                            <el-table-column prop="label" :label="t('formoption.label')" show-overflow-tooltip
                                             v-if="!hiddenFields.label">
                                <template #default="scope">
                                    <el-input v-model="scope.row.label" :placeholder="t('formoption.inputLabelTip')"
                                              :disabled="disabledFields.label"/>
                                </template>
                            </el-table-column>
                            <el-table-column prop="prop" :label="t('formoption.prop')" show-overflow-tooltip
                                             v-if="!hiddenFields.prop">
                                <template #default="scope">
                                    <el-input v-model="scope.row.prop" :placeholder="t('formoption.inputPropTip')"/>
                                </template>
                            </el-table-column>
                            <el-table-column prop="subForm" :label="t('formoption.subForm')" show-overflow-tooltip
                                             v-if="!hiddenFields.subForm">
                                <template #default="scope">
                                    <el-input v-model="scope.row.subForm"
                                              :placeholder="t('formoption.inputSubFormTip')"/>
                                </template>
                            </el-table-column>
                            <el-table-column prop="propType" :label="t('formoption.propType')" show-overflow-tooltip
                                             v-if="!hiddenFields.propType">
                                <template #default="scope">
                                    <el-input v-model="scope.row.propType"
                                              :placeholder="t('formoption.inputPropTypeTip')"/>
                                </template>
                            </el-table-column>

                            <el-table-column prop="permType" :label="t('formoption.permType')" show-overflow-tooltip
                                             v-if="!hiddenFields.permType">
                                <template #default="scope">
                                    <el-radio-group v-model="scope.row.permType">
                                        <el-radio v-for="(item, index) in DIC_PROP.FORM_PERM_TYPE" :key="index"
                                                  :label="item.value">
                                            {{ item.label }}
                                        </el-radio>
                                    </el-radio-group>
                                </template>
                            </el-table-column>
                        </el-table>
                    </el-form-item>
                </el-col>

            </el-row>
        </el-form>
        <footer class="el-dialog__footer" style="text-align: center;" v-if="!props.currFlowForm">
            <span class="dialog-footer">
              <el-button type="primary" @click="handleSubmit()" :disabled="loading">{{
                      $t('common.confirmButtonText')
                  }}</el-button>
                <el-button type="primary" @click="onClearSubmit" :disabled="loading" v-if="!validateNull(form.columns)">
                      清空
                  </el-button>
            </span>
        </footer>
    </div>
</template>

<script setup lang="ts" name="FormDefPerm">
    import {useMessage} from "/@/hooks/message";
    import {getObj, addObj, putObj, listFormOption} from '/@/api/jsonflow/form-option'
    import {useI18n} from "vue-i18n"
    import {setPropsNull, setPropsValue} from "/@/flow/support/common";
    import {onCascadeChange, onLoadDicUrl} from "/@/flow/components/convert-name/convert";
    import {validateNull} from "/@/utils/validate";
    import {initFromSomeAttrs, validateRunFlowId, parseWithFunctions, notifyLeft} from "/@/flow";
    import {buildFieldPerms} from "/@/flow/utils/form-perm";
    import {DIC_PROP} from "/@/flow/support/dict-prop";

    const emit = defineEmits(['refresh']);
    const {t} = useI18n();
    const $message = useMessage();

    // 定义变量内容
    const dataFormRef = ref();
    const loading = ref(false)
    const operType = ref(false);
    // 提交表单数据
    const form = reactive({
        id: '',
        flowKey: '',
        defFlowId: '',
        flowNodeId: '',
        columns: [],
        formType: '',
        formId: '',
        formName: '',
        path: '',
        printInfo: '',
        type: '',
    });

    // 定义校验规则
    const dataRules = ref({
        formType: [{required: true, message: '表单来源不能为空', trigger: 'blur'}],
        formId: [{required: true, message: '表单名称不能为空', trigger: 'blur'}],
        type: [{required: true, message: '数据类型不能为空', trigger: 'blur'}],
    })

    // 定义查询字典
    const dicData = reactive({});
    const cascadeDic = reactive({});
    const onLoad = onLoadDicUrl({key: "defFlowId"}, {key: "formId"});
    const onCascade = onCascadeChange(cascadeDic, {key: "defFlowId", cascades: ["flowNodeId"]});
    onMounted(async () => {
        await onLoad(dicData);

        // 判断是否设计器中
        if (props.currFlowForm) {
            await openDialog('add', null, '0')
        } else {
            let {type, id, dataType} = props.formDefPerm
            await openDialog(type, id, dataType)
        }
    });

    const props = defineProps({
        currFlowForm: {
            type: Object,
            default: null,
        },
        formDefPerm: {
            type: Object,
            default: null,
        },
    });

    function cascadeChange(key, cascades) {
        onCascade(form, {key: key, cascades: cascades});
        if (key === 'defFlowId') {
            let find = dicData.defFlowId.find(f => f.id === form.defFlowId);
            if (find) form.flowKey = find.flowKey
            else form.flowKey = null
        }
    }

    // 打开弹窗
    const openDialog = async (type, id, dataType) => {
        operType.value = type;
        form.id = ''

        // 重置表单数据
        nextTick(async () => {
            dataFormRef.value.resetFields()
            // 获取FormOption信息
            if (id) {
                form.id = id
                await getFormOptionData(id)
                await onCascade(form);
            }
            if (type === 'add') form.type = dataType
            typeChange(form.type);
            if (!props.currFlowForm) return
            validateRunFlowId(props, form)
            formIdChange(form.formId)
        })
    };

    const onClearSubmit = async () => {
        form.columns = []
        await handleSubmit()
    }

    const syncCurrFormInfo = (isClear) => {
        if (!isClear) props.currFlowForm.formFieldPerms = form.columns
        else props.currFlowForm.formFieldPerms = []
    }

    // 提交
    const handleSubmit = async (callback?) => {
        const valid = await dataFormRef.value.validate().catch(() => {
        });
        if (!valid) return false;

        if (!form.formId) {
            $message.warning("请先选择表单名称")
            return
        }
        if (form.type === DIC_PROP.FORM_DATA_TYPE[1].value && !form.flowNodeId) {
            $message.warning("请先选择节点名称")
            return
        }
        if (validateColumns()) return;
        initFromSomeAttrs(props, form)
        try {
            loading.value = true;
            await addObj(form);
            notifyLeft('当前表单设计保存成功')
            emit('refresh');
            if (callback) callback()
        } catch (err: any) {
            useMessage().error(err);
        } finally {
            loading.value = false;
        }
    }

    // 初始化表单数据
    const getFormOptionData = async (id: string) => {
        // 获取数据
        loading.value = true
        let res = await getObj(id);
        Object.assign(form, res.data)
        loading.value = false
    };

    // 定义字段显隐
    const hiddenFields = reactive({
        defFlowId: true,
        flowNodeId: true,
        label: true,
        prop: true,
        propId: true,
        subForm: true,
        propType: true,
        permType: true,
        printInfo: true,
    });

    // 定义字段是否可编辑
    const disabledFields = reactive({
        formType: false,
        label: false,
    });

    const formTypeChange = (value) => {
        if (value) dicData.formIdByType = dicData.formId.filter(f => f.type === value)
        else dicData.formIdByType = []
        form.columns = [];
        form.formId = null
    }

    const formIdChange = (value) => {
        form.columns = [];
        setPropsNull(form, 'flowKey', 'defFlowId', 'flowNodeId')
        if (!value) return
        if (form.type === DIC_PROP.FORM_DATA_TYPE[0].value) {
            handleCustomFormDef(value, form.type)
        }
        if (props.currFlowForm) return;
        let find = dicData.formIdByType.find(f => f.id === value);
        form.formName = find.formName
        form.path = find.path
    }

    // 查询字段信息
    function handleCustomFormDef(formId, type) {
        listFormOption({
                flowInstId: form.flowInstId,
                type: type, formType: form.formType, formId: formId
            }).then(resp => {
                let res = resp.data;
                if (!validateNull(res)) form.columns = res
                else form.columns = [];
            })
            .catch(() => {
                $message.error("获取表单字段定义失败");
            })
    }

    const changeFlowNodeId = (value) => {
        if (!value) {
            form.columns = [];
            return
        }
        handleCustomFormPerm(form.defFlowId, value, form.type)
    }

    function handleCustomFormPerm(defFlowId, flowNodeId, type) {
        listFormOption({
                type: type, formType: form.formType, formId: form.formId,
                defFlowId: defFlowId, flowInstId: form.flowInstId, flowNodeId: flowNodeId
            }).then(resp => {
                let res = resp.data;
                if (!validateNull(res)) form.columns = res
                else changeNodeFormId(form.formId)
            }).catch(() => {
                $message.error("获取表单字段权限失败");
            })
    }

    function changeNodeFormId(formId) {
        // 判断审批表单
        let find;
        if (form.formType === DIC_PROP.FORM_TYPE[0].value) {
            find = dicData.formIdByType.find(f => f.id === formId);
        } else {
            form.columns = [];
            $message.warning("当前选择的系统表单无字段信息，请点击《字段定义》按钮录入")
            return;
        }
        if (validateNull(find.formInfo)) {
            form.columns = [];
            $message.warning("当前选择的设计表单无字段信息，请先在《表单设计器》中设计")
            return;
        }
        let formInfo = parseWithFunctions(find.formInfo, true)
        buildFormFieldPerms(formInfo)
    }

    function buildFormFieldPerms(formInfo) {
        form.columns = []
        buildFieldPerms(form.columns, formInfo.widgetList);
    }

    const typeChange = (value) => {
        setPropsValue(disabledFields, false, 'formType', 'label')
        setPropsValue(hiddenFields, true, 'defFlowId', 'flowNodeId', 'propId', 'label', 'prop', 'subForm', 'propType', 'permType', 'printInfo')
        if (value === DIC_PROP.FORM_DATA_TYPE[0].value) {
            disabledFields.formType = true
            setPropsValue(hiddenFields, false, 'propId', 'label', 'prop', 'subForm', 'propType')
            form.formType = DIC_PROP.FORM_TYPE[1].value
        } else if (value === DIC_PROP.FORM_DATA_TYPE[1].value) {
            disabledFields.label = true
            setPropsValue(hiddenFields, false, 'defFlowId', 'flowNodeId', 'label', 'permType')
        } else {
            hiddenFields.printInfo = true
        }
        formTypeChange(form.formType)
    }

    const resetFormPerm = () => {
        if (!form.formId) {
            $message.warning("请先选择表单名称")
            return
        }
        handleCustomFormPerm(null, null, DIC_PROP.FORM_DATA_TYPE[0].value)
    }

    const onAddItem = () => {
        if (!form.formId) {
            $message.warning("请先选择表单名称")
            return
        }
        if (form.type === DIC_PROP.FORM_DATA_TYPE[1].value && !form.flowNodeId) {
            $message.warning("请先选择节点名称")
            return
        }
        if (validateColumns()) return;
        let obj = {propId: null, label: '', prop: '', subForm: null, propType: null, permType: null};
        form.columns.push(obj);
    }

    const validateColumns = () => {
        if (!validateNull(form.columns)) {
            let find = form.columns.find(s => !s.label || !s.prop);
            if (find) {
                $message.warning("请先填写 属性名称 或 属性名")
                return true
            }
        }
        return false
    }

    const handleDelete = (index: number, row: any) => {
        form.columns.splice(index, 1)
    }

    // 暴露变量
    defineExpose({
        openDialog, handleSubmit, syncCurrFormInfo
    });
</script>
