<template>
    <div>
        <div id="printInfo" style="word-break: break-all;" v-html="printInfoHtml"></div>
        <div>
            <footer class="el-dialog__footer" style="text-align: center;">
            <span class="dialog-footer">
                <el-button type="primary" @click="confirmClick">打印</el-button>
            </span>
            </footer>
        </div>
    </div>
</template>

<script setup lang="ts" name="TinymceView">
    import {printHtml, validateRunFlowId} from "/@/flow";
    import {validateNull} from "/@/utils/validate";
    import {onFormLoadedUrl, onLoadDicUrl} from "../convert-name/convert";
    import {PROP_CONST} from "../../support/prop-const";
    import {handleFormatValue, handlePrintValue} from "../form-create";
    import {buildFieldPerms} from "../../utils/form-perm";
    import {listFormOption} from "/@/api/jsonflow/form-option";
    import {useMessage} from "/@/hooks/message";
    import {DIC_PROP} from "../../support/dict-prop";

    const $message = useMessage();

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

    // 定义字典
    const dicData = reactive({});
    const onLoad = onLoadDicUrl();
    const onFormLoaded = onFormLoadedUrl();

    const printInfoHtml = ref(null)

    const data = reactive({
        formFields: [],
        // 自定义字段
        formDefFields: [],
    });

    async function initPrintInfoHtml(printInfo) {
        if (props.currFlowForm.rule) {
            buildFieldPerms(data.formFields, props.currFlowForm.rule, null, true)
        } else {
            // 初始化自定义字段
            data.formDefFields = handleCustomFormDef()
        }
        buildPrintInfoHtml(printInfo)
    }

    // 查询字段信息
    async function handleCustomFormDef() {
        if (validateNull(props.elTab)) return []
        // 判断流程实例独立配置
        let form = validateRunFlowId(props, {})
        let resp = await listFormOption({
            flowInstId: form.flowInstId,
            type: DIC_PROP.FORM_DATA_TYPE[0].value, formType: data.elTab.type, formId: data.elTab.id
        }).catch(() => {
            $message.error("获取表单字段定义失败");
        })
        return resp.data;
    }

    async function buildPrintInfoHtml(printInfo) {
        let regTable = /<\/tbody>.*?/g;
        let regTr = /<tr>.*?<\/tr>/g;
        let regSubVar = /\$\{.*?\..*?\}/g;
        let regVar = /\$\{.*?\}/g;
        printInfo = printInfo.replaceAll('\n', '')
        let tables = printInfo.split(regTable)
        for (let j = 0; j < tables.length; j++) {
            let table = tables[j]
            regSubVar.lastIndex = 0
            if (regSubVar.test(table)) {
                let newTable = table.replace(regTr, function (str) {
                    // 确保完整匹配
                    regSubVar.lastIndex = 0
                    if (regSubVar.test(str)) {
                        let propVar = str.substr(str.indexOf("${"), str.indexOf("}") - str.indexOf("${") + 1)
                        let prop = propVar.substring(propVar.indexOf("${") + 2, propVar.indexOf("."))
                        // 获取表格数据
                        let tableData = props.currFlowForm.formData[prop]
                        // 构造动态数据行
                        let dynamicRows = "";
                        if (!validateNull(tableData)) {
                            for (let i = 0; i < tableData.length; i++) {
                                let dynStr = str.replace(regSubVar, function (str) {
                                    let propVar = str.substr(str.indexOf("${"), str.indexOf("}") - str.indexOf("${") + 1)
                                    let prop = propVar.substring(propVar.indexOf(".") + 1, propVar.indexOf("}"))
                                    let existSubForm = validateSubFormField(props.currFlowForm.modelRefList, prop)
                                    let parProp = propVar.substring(propVar.indexOf("${") + 2, propVar.indexOf("}"))
                                    let formDatum = tableData[i][prop]
                                    if (existSubForm) {
                                        // 判断自定义组件
                                        let printValue = existSubForm.__fc__.prop.props.formCreateInject.printValue
                                        if (!printValue) {
                                            let optionItems = existSubForm.__fc__.prop.options
                                            printValue = handlePrintValue(optionItems, formDatum, 'value', 'label', parProp, existSubForm.type)
                                        }
                                        if (printValue) return printValue
                                    }
                                    if (!existSubForm) existSubForm = data.formFields.find(f => f.prop === parProp);
                                    // 自定义字段
                                    if (!existSubForm) existSubForm = data.formDefFields.find(f => f.subForm + '.' + f.prop === parProp);
                                    let propType = existSubForm ? existSubForm.propType || existSubForm.type : null
                                    return formDatum ? handleFormatValue(formDatum, formDatum, parProp, propType) : ''
                                })
                                dynamicRows += dynStr;
                            }
                        }
                        return dynamicRows;
                    } else {
                        return str;
                    }
                })
                printInfo = printInfo.replace(table, newTable);
            }
        }
        // 替换外层变量值
        if (regVar.test(printInfo)) {
            // 确保完整匹配
            regVar.lastIndex = 0
            const matches = [];
            let match;
            while ((match = regVar.exec(printInfo)) !== null) {
                matches.push({index: match.index, fullMatch: match[0], length: match[0].length});
            }
            // 为每个匹配项创建异步任务
            const promises = matches.map(async (match) => {
                const propVar = match.fullMatch;
                let prop = propVar.substring(propVar.indexOf("${") + 2, propVar.indexOf("}"))
                let formDatum = props.currFlowForm.formData[prop];
                let isSysFields = false, existForm = null;
                if (props.currFlowForm.rule) {
                    existForm = data.formFields.find(f => f.prop === prop);
                    if (existForm) {
                        // 判断自定义组件
                        let printValue = existForm.__fc__.prop.props.formCreateInject.printValue
                        if (!printValue) {
                            let optionItems = existForm.__fc__.prop.options
                            printValue = handlePrintValue(optionItems, formDatum, 'value', 'label', prop, existForm.propType)
                        }
                        if (printValue) return printValue;
                    } else {
                        isSysFields = true;
                    }
                } else {
                    let optionItems = props.currFlowForm.dicData[prop];
                    if (!validateNull(optionItems)) {
                        let valueKey = props.currFlowForm[prop + '.valueKey']
                        let showKey = props.currFlowForm[prop + '.showKey']
                        existForm = data.formDefFields.find(f => f.prop === prop);
                        let propType = existForm ? existForm.propType : null
                        let printValue = handlePrintValue(optionItems, formDatum, valueKey, showKey, prop, propType)
                        if (printValue) return printValue;
                    } else {
                        isSysFields = true;
                    }
                }
                if (isSysFields) {
                    formDatum = props.currFlowForm[prop];
                    let field = PROP_CONST.SYS_FIELDS.find(f => f.prop === prop);
                    if (!validateNull(field) && field.valueKey) {
                        await onFormLoaded(dicData, {[prop]: formDatum}, {key: prop});
                        let find = dicData[prop].find(f => f[field.valueKey] === formDatum);
                        existForm = data.formDefFields.find(f => f.prop === prop);
                        let propType = existForm ? existForm.propType : null
                        if (find) return handleFormatValue(find[field.showKey], find[field.showKey], prop, propType)
                    }
                }
                let propType = existForm ? existForm.propType : null
                return formDatum ? handleFormatValue(formDatum, formDatum, prop, propType) : ''
            })
            const replacements = await Promise.all(promises);
            // 从后往前替换，避免索引变化问题
            let dynStr = printInfo;
            for (let i = matches.length - 1; i >= 0; i--) {
                const match = matches[i];
                const replacement = replacements[i];
                dynStr = dynStr.substring(0, match.index) + replacement + dynStr.substring(match.index + match.length);
            }
            printInfo = dynStr;
        }
        printInfoHtml.value = printInfo
    }

    function validateSubFormField(modelRefList, field) {
        if (validateNull(modelRefList)) return null
        let resExistField = null
        for (const each of modelRefList) {
            if (validateNull(each.model())) continue
            let existField = each.model()[field];
            if (existField) {
                resExistField = existField
                break;
            }
        }
        return resExistField
    }

    function confirmClick() {
        printHtml("printInfo", props.currFlowForm.formName, null)
    }

    // 监听变化
    watch(
        () => props.currFlowForm.id,
        () => {
            initPrintInfoHtml(props.currFlowForm.printInfo);
        }
    );

    // 初始化
    onMounted(async () => {
        // await onLoad(dicData);
        initPrintInfoHtml(props.currFlowForm.printInfo);
    });

</script>

<style lang="scss">
  // 排除tailwind.css全局样式的影响
  /*border-width: 0;
  border-style: solid;*/
  #printInfo {
    table, th, td {
      border: 1px solid; /* 设置边框样式 */
      border-collapse: collapse; /* 合并边框 */
    }
  }
  /*img { TODO 本地设置默认大小
    width: 660px;
    height: 150px;
  }*/
</style>
