<template>
  <!-- 表单信息 -->
  <div class="form-container">
    <div class="box">
      <div class="form-left relative" :style="{ width: formLeft }" @mousedown="handleLeftDown">
        <div class="resize-shrink-sidebar" id="approval-form-left" title="收缩侧边栏">
          <span class="shrink-sidebar-text">⋮</span>
        </div>
        <div class="left-title">
          <div v-show="showPanel">{{ t('表单信息') }}</div>
          <div
            @click="changeShowPanel"
            class="in-or-out"
            :style="{ right: showPanel ? '10px' : '16px' }"
          >
            <component :is="fewerPanelComponent" />
          </div>
        </div>
        <div class="left-box">
          <div
            v-for="(item, index) in forms.configs"
            :key="index"
            :class="activeIndex == index ? 'form-name actived' : 'form-name'"
          >
            <span :class="item.validate ? 'dot' : 'dot validate'"></span>
            <div class="icon-box">
              <IconFontSymbol
                icon="mianxing-biaodan"
                :fillColor="activeIndex == index ? '#1c8dff' : '#333333'"
              /> </div
            ><span @click="changeActiveIndex(index)" v-show="showPanel">{{ item.formName }}</span>
          </div>
          <FormFlowRecord :processId="processId" v-if="processId" />
        </div>
      </div>
      <div class="form-right h-full" :style="{ paddingLeft: formRight }">
        <template v-for="(item, index) in forms.configs" :key="index">
          <div v-show="activeIndex == index" class="h-full">
            <SystemForm
              class="form-box"
              v-if="item.formType == FormType.SYSTEM"
              :systemComponent="item.systemComponent"
              :isViewProcess="props.disabled"
              :formModel="item.formModel"
              :workflowConfig="item"
              :ref="setItemRef"
            />
            <SimpleForm
              v-else-if="item.formType == FormType.CUSTOM"
              class="form-box"
              :ref="setItemRef"
              :formProps="item.formProps"
              :formModel="item.formModel"
              :isWorkFlow="true"
            />
          </div>
        </template>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import SimpleForm from '/@/components/SimpleForm/src/SimpleForm.vue';
  import { FewerLeft, FewerRight } from '/@/components/ModalPanel';
  import FormFlowRecord from './FormFlowRecord.vue';
  import IconFontSymbol from '/@/components/IconFontSymbol/Index.vue';
  import { onBeforeUpdate, nextTick, onMounted, reactive, computed, ref, provide } from 'vue';
  import { TaskApproveOpinion, ValidateForms } from '/@/model/workflow/bpmnConfig';
  import { cloneDeep } from 'lodash-es';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { GeneratorConfig } from '/@/model/generator/generatorConfig';
  import { FormEventColumnConfig } from '/@/model/generator/formEventConfig';
  import { changeFormJson } from '/@/hooks/web/useWorkFlowForm';
  import { SystemForm } from '/@/components/SystemForm/index';
  import { FormType } from '/@/enums/workflowEnum';
  import {
    createFormEvent,
    getFormDataEvent,
    loadFormEvent,
    submitFormEvent,
  } from '/@/hooks/web/useFormEvent';
  import { FormProps } from '/@/components/Form';
  const { t } = useI18n();
  const props = withDefaults(
    defineProps<{
      disabled: boolean | undefined;
      formInfos: Array<any>;
      opinions?: Array<TaskApproveOpinion> | undefined;
      opinionsComponents?: Array<string> | undefined;
      formAssignmentData?: null | Recordable;
      processId: string | undefined;
    }>(),
    {
      disabled: false,
      formInfos: () => {
        return [];
      },
    },
  );

  const emits = defineEmits(['getFormConfigs']);
  provide('formAssignmentData', props.formAssignmentData); // formAssignmentData 流程参数
  let formLeft = ref('24%');
  let formRight = ref('calc(24% + 16px)');
  let showPanel = ref(true);
  let uploadComponent: { ids: Array<string> } = reactive({ ids: [] });
  let fewerPanelComponent = computed(() => {
    return showPanel.value ? FewerLeft : FewerRight;
  });

  let activeIndex = ref(0);
  let itemRefs = ref([]) as any;
  const setItemRef = (el: never) => {
    itemRefs.value.push(el);
  };
  function showRightBox() {
    formLeft.value = '24%';
    formRight.value = 'calc(24% + 16px)';
  }
  function hideRightBox() {
    formLeft.value = '52px';
    formRight.value = '78px';
  }
  function changeShowPanel() {
    showPanel.value = !showPanel.value;
    if (showPanel.value) {
      showRightBox();
    } else {
      hideRightBox();
    }
  }
  onBeforeUpdate(() => {
    itemRefs.value = [];
  });
  let forms: {
    formModels: Array<Recordable>;
    configs: Array<{
      formId: string;
      formName: string;
      formProps: FormProps;
      formModel: Recordable;
      formKey: string;
      validate: boolean;
      formType: FormType;
      workflowPermissions?: Array<any>;
      opinions?: Array<any>;
      opinionsComponents?: Array<any>;
      systemComponent?: {
        functionalModule: string;
        functionName: string;
        functionFormName: string;
      };
      formJson?: Array<any>;
      isOldSystem?: boolean;
    }>;
    formEventConfigs: FormEventColumnConfig[];
  } = reactive({
    formModels: [],
    configs: [],
    formEventConfigs: [],
  });
  onMounted(async () => {
    for await (let element of props.formInfos) {
      let formModels = {};
      if (element.formData) {
        formModels = cloneDeep(element.formData);
      }
      // 参数赋值[赋值权限最大]
      if (props.formAssignmentData) {
        if (props.formAssignmentData[element.formConfig.formId]) {
          formModels = { ...formModels, ...props.formAssignmentData[element.formConfig.formId] };
        }
      }

      forms.formModels.push(formModels);

      // 系统表单
      if (element.formType == FormType.SYSTEM) {
        const model = JSON.parse(element.formJson) as GeneratorConfig;
        const { formJson } = model;

        let isViewProcess = props.disabled;
        let { buildOptionJson } = changeFormJson(
          {
            formJson,
            formConfigChildren: element.formConfig.children,
            formConfigKey: element.formConfig.key,
            opinions: props.opinions,
            opinionsComponents: props.opinionsComponents,
          },
          isViewProcess,
          uploadComponent.ids,
        );
        forms.configs.push({
          formId: element.formConfig.formId,
          formName: element.formConfig.formName,
          formProps: buildOptionJson.schemas ? buildOptionJson : {},
          formModel: formModels,
          formKey: element.formConfig.key,
          validate: true,
          formType: element.formType,
          workflowPermissions: element.formConfig.children,
          opinions: props.opinions,
          opinionsComponents: props.opinionsComponents,
          systemComponent: {
            functionalModule: element.functionalModule,
            functionName: element.functionName,
            functionFormName: 'Form',
          },
          formJson: element.formJson,
          isOldSystem: false,
        });
        // 上传组件Id集合
        setTimeout(() => {
          getSystemUploadComponentIds();
        }, 1000);
      } else {
        const model = JSON.parse(element.formJson) as GeneratorConfig;
        const { formJson, formEventConfig } = model;

        if (formEventConfig) {
          forms.formEventConfigs.push(formEventConfig);
          //初始化表单
          await createFormEvent(
            formEventConfig,
            formModels,
            formJson.list,
            false,
            element.formConfig.formName,
            element.formConfig.formId,
          );
          //加载表单
          await loadFormEvent(
            formEventConfig,
            formModels,
            formJson.list,
            false,
            element.formConfig.formName,
            element.formConfig.formId,
          );

          //TODO 暂不放开 工作流没有获取表单数据这个步骤 获取表单数据
          // getFormDataEvent(formEventConfig, formModels,true);
        }
        let formKey = element.formConfig.key;

        let config = {
          formId: element.formConfig.formId,
          formName: element.formConfig.formName,
          formProps: {},
          formModel: {},
          formKey,
          validate: true,
          formType: element.formType,
        };
        let isViewProcess = props.disabled;
        let { buildOptionJson, uploadComponentIds } = changeFormJson(
          {
            formJson,
            formConfigChildren: element.formConfig.children,
            formConfigKey: element.formConfig.key,
            opinions: props.opinions,
            opinionsComponents: props.opinionsComponents,
          },
          isViewProcess,
          uploadComponent.ids,
        );
        uploadComponent.ids = uploadComponentIds;
        if (buildOptionJson.schemas) {
          config.formProps = buildOptionJson;
          forms.configs.push(config);
        }
      }
      // });
    }

    await nextTick();
    setTimeout(async () => {
      await setFormModel();
    }, 0);
    emits('getFormConfigs', forms.configs.length ? forms.configs[activeIndex.value] : null);
  });

  async function setFormModel() {
    for (let index = 0; index < itemRefs.value.length; index++) {
      if (itemRefs.value[index]) {
        if (forms.configs[index].formType === FormType.CUSTOM) {
          itemRefs.value[index].setDefaultValue();
          if (forms.formEventConfigs[index]) {
            //初始化表单
            await createFormEvent(
              forms.formEventConfigs[index],
              forms.formModels[index],
              itemRefs.value[index],
              forms.configs[index].formProps.schemas,
              false,
            );
            //加载表单
            await loadFormEvent(
              forms.formEventConfigs[index],
              forms.formModels[index],
              itemRefs.value[index],
              forms.configs[index].formProps.schemas,
              false,
            );
          }

          setTimeout(async () => {
            itemRefs.value[index].setFieldsValue(forms.formModels[index]);
            if (forms.formEventConfigs[index]) {
              // 获取表单数据
              await getFormDataEvent(
                forms.formEventConfigs[index],
                forms.formModels[index],
                itemRefs.value[index],
                forms.configs[index].formProps.schemas,
                true,
              );
            }
          }, 200);
        } else {
          itemRefs.value[index].setFieldsValue(forms.formModels[index]);
        }
      }
    }
  }

  async function setFormData(formData) {
    await nextTick();
    forms.formModels = formData;
    setFormModel();
  }

  function changeActiveIndex(index: number) {
    activeIndex.value = index;
    emits('getFormConfigs', forms.configs[activeIndex.value]);
  }
  function getSystemUploadComponentIds() {
    for (let index = 0; index < itemRefs.value.length; index++) {
      if (itemRefs.value[index] && itemRefs.value[index].getUploadComponentIds) {
        let ids = itemRefs.value[index].getUploadComponentIds();
        uploadComponent.ids = [...uploadComponent.ids, ...ids];
      }
    }
  }
  // 获取上传组件的字段值集合
  function getUploadComponentIds() {
    return uploadComponent.ids;
  }
  async function validateForm() {
    let validateForms: ValidateForms = [];
    for (let index = 0; index < itemRefs.value.length; index++) {
      if (itemRefs.value[index]) {
        try {
          await itemRefs.value[index]?.validate();
          validateForms.push({
            validate: true,
            msgs: [],
            isOldSystem: forms.configs[index].isOldSystem,
          });
          forms.configs[index].validate = true;
        } catch (error: any | Array<{ errors: Array<string>; name: Array<string> }>) {
          validateForms.push({
            validate: false,
            msgs: error?.errorFields,
          });
          forms.configs[index].validate = false;
        }
      }
    }
    return validateForms;
  }

  async function saveDraftData() {
    let formModes = {};

    for (let index = 0; index < forms.configs.length; index++) {
      const ele = forms.configs[index];
      if (ele.formType == FormType.SYSTEM) {
        let values = await itemRefs.value[index].getFieldsValue();
        formModes[ele.formKey] = values;
      } else {
        formModes[ele.formKey] = ele.formModel;
      }
    }
    return formModes;
  }
  async function getFormModels() {
    let formModes = {};

    for (let index = 0; index < forms.configs.length; index++) {
      const ele = forms.configs[index];
      if (ele.formType == FormType.SYSTEM) {
        let values = await itemRefs.value[index].workflowSubmit();
        formModes[ele.formKey] = values;
      } else {
        formModes[ele.formKey] = ele.formModel;
      }
    }

    // forms.configs.forEach((ele) => {
    //   formModes[ele.formKey] = ele.formModel;
    // });
    forms.formEventConfigs.forEach(async (ele, i) => {
      //此组件 获取数据 就是为了提交表单 所以 表单提交数据 事件 就此处执行
      await submitFormEvent(
        ele,
        forms.configs[i]?.formModel,
        itemRefs.value[i],
        forms.configs[i].formProps.schemas,
        false,
        forms.configs[i]?.formName,
        forms.configs[i]?.formId,
      );
    });
    return formModes;
  }
  function getSystemType() {
    let system = {};
    for (let index = 0; index < forms.configs.length; index++) {
      const ele = forms.configs[index];
      if (ele.formType == FormType.SYSTEM) {
        system[ele.formKey] = itemRefs.value[index].getIsOldSystem();
      }
    }
    return system;
  }
  function handleLeftDown(e) {
    let resize = document.getElementById('approval-form-left') as any;
    let startX = e.clientX;
    let left = resize?.offsetLeft || 0;

    document.onmousemove = function (e) {
      let endX = e.clientX;
      let moveLen = left + (endX - startX);
      if (moveLen <= 110) {
        showPanel.value = false;
      } else {
        showPanel.value = true;
      }
      if (moveLen <= 52) moveLen = 52;
      formLeft.value = moveLen + 'px';
      formRight.value = moveLen + 20 + 'px';
    };
    document.onmouseup = function () {
      document.onmousemove = null;
      document.onmouseup = null;
      resize.releaseCapture && resize.releaseCapture();
    };
  }
  async function sendMessageForAllIframe() {
    for (let index = 0; index < itemRefs.value.length; index++) {
      if (itemRefs.value[index] && itemRefs.value[index].sendMessageForAllIframe) {
        itemRefs.value[index].sendMessageForAllIframe();
      }
    }
  }
  defineExpose({
    validateForm,
    getFormModels,
    saveDraftData,
    setFormData,
    getUploadComponentIds,
    getSystemType,
    sendMessageForAllIframe,
  });
</script>

<style lang="less" scoped>
  .form-container {
    display: flex;
    height: 100%;
  }

  .box {
    width: 100%;

    .form-left {
      float: left;
      height: 100%;
      z-index: 9998;
      border-right: 1px solid #eee;

      .resize-shrink-sidebar {
        cursor: col-resize;
        display: flex;
        justify-content: center;
        align-items: center;
        position: absolute;
        top: 0;
        bottom: 0;
        right: 0;
        z-index: 9999;

        .shrink-sidebar-text {
          padding: 0 2px;
          background: #f2f2f2;
          border-radius: 10px;
        }
      }

      .left-box {
        height: calc(100% - 50px);
      }

      span {
        font-size: 16px;
        font-weight: 500;
        padding-left: 4px;
      }

      .form-name {
        height: 40px;
        display: flex;
        align-items: center;
        font-size: 14px;
        cursor: pointer;
        color: #333;
      }

      .actived {
        border-right: 4px solid @primary-color;
        color: @primary-color;
        background: #f7fbff;
      }

      .dot {
        width: 10px;
        height: 10px;
        border-radius: 50%;
        background-color: transparent;
        margin-right: 4px;
      }

      .validate {
        background-color: @clear-color;
      }

      .icon-box {
        font-size: 16px;
        margin-right: 4px;
      }

      .left-title {
        display: flex;
        justify-content: space-between;
        align-items: center;
        position: relative;
        padding-left: 16px;
        font-weight: bold;
        font-size: 16px;
        height: 50px;
        border-bottom: 1px solid #eee;

        .in-or-out {
          position: absolute;
          top: 15px;
          right: 10px;
          z-index: 3;
          width: 20px;
          height: 20px;
          background: #fff;
          border-radius: 4px;
          border: 1px solid #ddd;
          text-align: center;
          line-height: 20px;
        }
      }
    }

    .form-box {
      overflow: auto;
      height: 100%;
      padding-right: 7px;
      margin-right: -7px;
    }

    .form-right {
      width: 100%;
      padding: 16px 16px 16px 0;
    }
  }
</style>
