<template>
  <LoadingBox v-if="showLoading" />
  <ProcessLayout class="wrap" v-if="visible">
    <template #title> {{ t('发起流程') }}【{{ data.item.name }}】 </template>
    <template #close>
      <a-button type="primary" class="clean-icon" @click.stop="$emit('close')">{{
        t('关闭')
      }}</a-button>
    </template>
    <template #left>
      <FlowPanel
        :xml="data.xml"
        :taskRecords="[]"
        :predecessorTasks="selectedPredecessorTasks"
        processId=""
        position="top"
      >
        <FormInformation
          :opinionsComponents="data.opinionsComponents"
          :opinions="data.opinions"
          :disabled="false"
          :formInfos="data.formInfos"
          :formAssignmentData="data.formAssignmentData"
          ref="formInformation"
          @get-form-configs="
            () => {
              data.submitLoading = false;
            }
          "
        />
      </FlowPanel>
    </template>
    <template #right>
      <div class="launch-box">
        <div class="description-box">
          <div class="title">{{ t('发起流程') }}</div>
          <ProcessInfo class="item-box" :item="data.item" />
        </div>
        <PredecessorTask
          v-if="data.relationTasks && data.relationTasks.length > 0"
          @change="changePredecessorTasks"
          :schemaId="schemaId"
          :relationTasks="data.predecessorTasks"
        />
        <ApproveUser
          v-if="approveUserData.visible"
          :taskList="approveUserData.list"
          :schemaId="approveUserData.schemaId"
          @change="changeApproveUserData"
        />
        <div class="button-box">
          <a-button
            type="primary"
            class="!mt-0 !mb-10px !rounded"
            :disabled="isPublish || data.submitLoading"
            :loading="data.submitLoading"
            v-debounce:click="saveLaunch"
            >{{ t('发起') }}</a-button
          >
          <a-button class="!m-0 !rounded" v-debounce:click="saveDraft">{{
            t('保存草稿')
          }}</a-button>
        </div>
      </div>
    </template>
  </ProcessLayout>
</template>

<script setup lang="ts">
  import ProcessLayout from './flow/Layout.vue';
  import FlowPanel from './flow/FlowPanel.vue';
  import FormInformation from './flow/FormInformation.vue';
  import { LoadingBox } from '/@/components/ModalPanel/index';
  import ProcessInfo from './flow/ProcessInfo.vue';
  import PredecessorTask from './PredecessorTask.vue';

  import ApproveUser from './flow/ApproveUser.vue';
  import { getWithdrawTasks, postDraft, putDraft } from '/@/api/workflow/process';
  import {
    postLaunch,
    getStartProcessInfo,
    getReStartProcessInfo,
    reLaunch,
  } from '/@/api/workflow/task';
  import { computed, onMounted, ref, toRaw, nextTick } from 'vue';
  import { ApproveTask, SchemaTaskItem } from '/@/model/workflow/bpmnConfig';
  import userTaskItem from './../hooks/userTaskItem';
  import { separator } from '../../design/bpmn/config/info';
  import { useI18n } from '/@/hooks/web/useI18n';
  const { t } = useI18n();
  const props = defineProps({
    schemaId: {
      type: String,
      required: true,
    },
    draftsJsonStr: {
      type: String,
    },
    draftsId: {
      type: String,
    },
    taskId: {
      type: String,
      required: false,
      default: '',
    },
    processId: {
      type: String,
      required: false,
      default: '',
    },
    formData: {
      type: Object,
    },
    formId: {
      type: String,
    },
    rowKeyData: {
      type: String,
    },
    withdrawId: {
      type: String,
    },
    isWithdraw: {
      type: Boolean,
      default: false,
    },
  });
  let emits = defineEmits(['close']);
  let formInformation = ref();
  let visible = ref(false);
  let showLoading = ref(false);
  const curDraftsId = ref();
  const { data, approveUserData, initProcessData, notificationError, notificationSuccess } =
    userTaskItem();

  const selectedPredecessorTasks = computed(() => {
    return data.predecessorTasks.filter((ele) => {
      return ele.taskId;
    });
  });
  const isPublish = ref(true);
  onMounted(async () => {
    try {
      if (props.withdrawId) {
        //撤回
        let res = await getWithdrawTasks(props.taskId, props.withdrawId);
        res.taskApproveOpinions = [];
        initProcessData(res);
        showLoading.value = false;
      } else if (props.processId) {
        // 重新发起
        let res = await getReStartProcessInfo(props.taskId, props.processId);
        res.taskApproveOpinions = [];
        initProcessData(res);
        showLoading.value = false;
      } else if (props.schemaId && props.formId) {
        let res = await getStartProcessInfo(props.schemaId);

        if (props.formData && props.formId) {
          res.formInfos.map((m) => {
            if (m.formConfig.formId === props.formId) {
              m.formData = toRaw(props.formData);
            }
          });
        }
        initProcessData(res);
        showLoading.value = false;
      } else {
        // 发起流程
        let res = await getStartProcessInfo(props.schemaId);
        initProcessData(res);
        // formData 全部赋值
        data.formInfos.map((info) => {
          if (info.formData == undefined) {
            const formDataInfo = {};
            info.formConfig.children.forEach((element) => {
              // 被隐藏的字段需要赋值默认值
              if (element.isSubTable && !element.view) {
                formDataInfo[element.tableName] = [];
              } else {
                if (!element.view) formDataInfo[element.fieldId] = element.defaultValue;
              }
            });
            info.formData = formDataInfo;
          }
        });
        showLoading.value = false;
      }
    } catch (error) {
      showLoading.value = false;
    }

    showLoading.value = false;
    visible.value = true;
    await nextTick();
    initDraftsFormData();
  });
  async function initDraftsFormData() {
    isPublish.value = Object.keys(data.formInfos).length > 0 ? false : true;
    if (props.draftsJsonStr) {
      let formDataJson = JSON.parse(props.draftsJsonStr);
      let formData: Array<any> = [];

      data.formInfos.forEach((item) => {
        if (
          formDataJson &&
          item.formConfig &&
          item.formConfig.key &&
          formDataJson[item.formConfig.key]
        ) {
          formData.push(item.formConfig.key ? formDataJson[item.formConfig.key] : {});
        }
      });
      await formInformation.value.setFormData(formData);
    }
  }
  function getUploadFileFolderIds(formModels) {
    let fileFolderIds: Array<string> = [];
    let uploadComponentIds = formInformation.value.getUploadComponentIds();
    uploadComponentIds.forEach((ids) => {
      if (ids.includes(separator)) {
        let arr = ids.split(separator);
        if (arr.length == 2 && formModels[arr[0]][arr[1]]) {
          fileFolderIds.push(formModels[arr[0]][arr[1]]);
        } else if (
          arr.length == 3 &&
          formModels[arr[0]][arr[1]] &&
          Array.isArray(formModels[arr[0]][arr[1]])
        ) {
          formModels[arr[0]][arr[1]].forEach((o) => {
            fileFolderIds.push(o[arr[2]]);
          });
        }
      }
    });
    return fileFolderIds;
  }
  async function saveLaunch() {
    formInformation.value.sendMessageForAllIframe(); //iframe 发送消息到对应网址
    data.submitLoading = true;
    try {
      let validateForms = await formInformation.value.validateForm();
      let system = formInformation.value.getSystemType();

      if (validateForms.length > 0) {
        let successValidate = validateForms.filter((ele) => {
          return ele.validate;
        });
        if (successValidate.length == validateForms.length) {
          let formModels = await formInformation.value.getFormModels();
          let relationTasks: Array<{
            schemaId: string;
            taskId: string;
          }> = [];
          if (data.predecessorTasks && data.predecessorTasks.length > 0) {
            relationTasks = data.predecessorTasks.map((ele) => {
              return { taskId: ele.taskId, schemaId: ele.schemaId };
            });
          }
          let fileFolderIds: Array<string> = getUploadFileFolderIds(formModels);
          //如果传入了processId  代表是重新发起流程
          let res;
          if (props.processId) {
            res = await reLaunch(
              props.processId,
              props.schemaId,
              formModels,
              relationTasks,
              fileFolderIds,
              system,
              props.isWithdraw,
            );
          } else {
            res = await postLaunch(
              props.schemaId,
              formModels,
              relationTasks,
              fileFolderIds,
              system,
              props.isWithdraw ? props.taskId : '',
              props.draftsId ? props.draftsId : curDraftsId.value,
            );
          }

          // 下一节点审批人
          let taskList: Array<ApproveTask> = [];
          if (res && res.length > 0) {
            taskList = res
              .filter((ele) => {
                return ele.isMultiInstance == false && ele.isAppoint == true;
              })
              .map((ele) => {
                return {
                  taskId: ele.taskId,
                  taskName: ele.taskName,
                  provisionalApprover: ele.provisionalApprover,
                  selectIds: [],
                };
              });
            if (taskList.length > 0) {
              approveUserData.list = taskList;
              approveUserData.schemaId = props.schemaId;
              approveUserData.visible = true;
              data.submitLoading = false;
            } else {
              data.submitLoading = false;
              save(true, t('发起流程'));
            }
          } else {
            data.submitLoading = false;
            save(true, t('发起流程'));
          }
        } else {
          data.submitLoading = false;
          notificationError(t('发起流程'), t('表单校验未通过'));
        }
      }
    } catch (error) {
      data.submitLoading = false;
      // 表单提交错误，流程已转入草稿箱
      try {
        let formModels = await formInformation.value.saveDraftData();
        if (props.draftsId) curDraftsId.value = props.draftsId;
        if (curDraftsId.value) {
          await putDraft(props.schemaId, formModels, curDraftsId.value, props.rowKeyData);
        } else {
          await postDraft(props.schemaId, formModels, props.rowKeyData);
        }
      } catch (error) {}
    }
  }
  async function saveDraft() {
    try {
      let formModels = await formInformation.value.saveDraftData();
      if (props.draftsId) {
        curDraftsId.value = props.draftsId;
        let res = await putDraft(props.schemaId, formModels, props.draftsId, props.rowKeyData);
        save(res, t('保存草稿'));
      } else {
        let res = await postDraft(props.schemaId, formModels, props.rowKeyData);
        curDraftsId.value = res;
        save(res, t('保存草稿'));
      }
    } catch (error) {
      notificationError(t('保存草稿'));
    }
  }
  function changePredecessorTasks(list: Array<SchemaTaskItem>) {
    data.predecessorTasks = list;
  }
  function save(res: boolean, title: string) {
    if (res) {
      notificationSuccess(title);
      emits('close');
    } else {
      notificationError(title);
    }
  }

  function changeApproveUserData() {
    approveUserData.visible = false;
    emits('close');
  }
</script>
<style lang="less" scoped>
  .description-box {
    color: rgb(102 102 102 / 99.6%);
    margin-bottom: 20px;

    .title {
      margin-bottom: 16px;
      font-weight: bold;
      font-size: 14px;
      color: #333;
      line-height: 14px;
      border-bottom: 1px solid #eee;
      width: 100%;
      height: 50px;
      padding: 19px 0 0 10px;
    }
  }

  .button-box {
    border-top: 1px solid #eee;
    padding: 16px 10px 0;
  }
</style>
