<template>
  <div id="formPreview" v-loading="state.loading"/>
</template>
<script lang="ts" setup>
  import { PropType, reactive, onDeactivated } from 'vue';
  import { loadMicroApp, MicroApp } from 'qiankun';
  import { getSubDefineProps } from '/@/qiankun/state';
  import { GlStateEnum } from '/@/enums/microAppEnum';
  import { useMicroAppStore } from '/@/store/modules/microApp';
  import { apps } from '/@/qiankun/apps';
  import { getFormDefinitionJson } from '/@/api/platform/workflow/extension/controller/formDefinitionJson';
  import { FORM_DESIGN_APP_COMPONENTS } from '/@/enums/microAppEnum';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { startProcessDefinition, auditTask } from '/@/api/platform/workflow/controller/form';
  import type { Workflow } from '/@/api/platform/workflow/entity/workflow';

  const props = defineProps({
    taskFormData: {
      type: Array as PropType<Recordable[]>,
      default: () => []
    },
    disabled: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    readonly: {
      type: Boolean as PropType<boolean>,
      default: false
    }
  });

  interface WindowState {
    formDesignApp: MicroApp;
    formData: Recordable;
    options: Recordable;
    loading: boolean;
  }

  const state = reactive<WindowState>({
    formDesignApp: undefined!,
    loading: false,
    formData: {},
    options: {}
  });
  const formDesignProps = {
    style: { 'min-height': '50px' },
    options: {},
    disabled: props.disabled,
    readonly: props.readonly,
    value: state.formData,
    handleValueChange: (formData: Recordable) =>
        formDesignProps.value = state.formData = formData
  };
  const microAppStore = useMicroAppStore();
  const { createMessage } = useMessage();

  async function init(formJsonId: string) {
    if (formJsonId) {
      state.loading = true;
      state.formData = {};
      // 处理表单json数据渲染
      try {
        const data = await getFormDefinitionJson(formJsonId);
        if (!data.json) throw Error('当前数据没有json结构体');
        formDesignProps.options = eval('(' + data.json + ')');
        const disableIds: string[] = [], showIds: string[] = [];
        props.taskFormData.forEach((item) => {
          if (item.value !== undefined) {
            state.formData[item.id] = item.value;
          }
          if (item.readable === true) {
            showIds.push(item.id);
          }
          if (item.writable === false) {
            disableIds.push(item.id);
          }
        });
        // todo: 待优化
        formDesignProps.value = state.formData;
        state.formDesignApp?.unmount();
        state.formDesignApp = loadMicroApp(Object.assign({} , apps.find(item => item.name == 'form-design'), {
          container: '#formPreview',
          props: {
            ...getSubDefineProps(),
            mountApp: FORM_DESIGN_APP_COMPONENTS.PREVIEW,
            // 表单设计器props
            [GlStateEnum.FORM_DESIGN_APP_PROPS_KEY]: formDesignProps
          }
        }), { sandbox: { experimentalStyleIsolation: true }});
        state.formDesignApp.mountPromise.then(() => {
          const formPreviewApp: Recordable = microAppStore.getFormDesignApp(FORM_DESIGN_APP_COMPONENTS.PREVIEW),
                formRef: Recordable = formPreviewApp.getRef().$refs['form-preview'];
          formRef.setShowIds(showIds);
          formRef.setDisableIds(disableIds);
          state.loading = false;
        });
      } catch(e: any) {
        createMessage.error(e);
        state.loading = false;
      }
    } else createMessage.info('没有关联流程表单!');
  }

  onDeactivated(() => {
    state.formDesignApp?.unmount();
  });

  async function startFormProcessDefinition(data: Partial<Workflow>, callback: Fn) {
    const processVarsity = Object.assign(data.vars || {}, state.formData);
    const processInsId = await startProcessDefinition({ ...data, vars: processVarsity });
    callback(processInsId);
  }

  async function auditFormTask(data: Partial<Workflow>, callback: Fn) {
    const processVarsity = Object.assign(data.vars || {}, state.formData);
    await auditTask({...data, vars: processVarsity});
    callback();
  }

  defineExpose({
    init,
    startFormProcessDefinition,
    auditFormTask
  });

</script>
