<template>
  <div class="launch-add page-wrapper">
    <div class="page-container">
      <a-collapse
        v-for="item in formData"
        :key="item.taskCode"
        :bordered="false"
        default-active-key="first"
        expand-icon-position="right"
        class="collapse-header-divide"
      >
        <a-collapse-panel key="first" :header="$t('BUSINESS_FORM')">
          <BpmnForm
            :key="`${item.formCode}${key}`"
            :ref="`${item.formCode}BpmnFormBlock`"
            :mark="item.formCode"
            :form-business-id="item.formBusinessId"
            :disabled="!(currentForm && item.formCode === currentForm.formCode)"
          />
        </a-collapse-panel>
      </a-collapse>

      <a-collapse
        :bordered="false"
        default-active-key="first"
        expand-icon-position="right"
        class="collapse-header-divide"
      >
        <a-collapse-panel key="first" :header="$t('APPROVAL_COMMENT')">
          <MomTable
            :columns="approveTableColumns"
            :data-source="approveTableData"
            :action-buttons="[]"
            :pagination="false"
            :show-util-operator="false"
            :whole="false"
            :mega-extend="{
              rowAction: false,
            }"
          />
        </a-collapse-panel>
      </a-collapse>

      <a-collapse
        :bordered="false"
        default-active-key="first"
        expand-icon-position="right"
        class="collapse-header-divide flowable"
      >
        <a-collapse-panel
          key="first"
          :header="$t('FLOW_CHART')"
          class="bpmn-container"
        >
          <BpmnReadonly :key="key" :xml-data="xmlData" />
        </a-collapse-panel>
      </a-collapse>
    </div>
    <div class="page-bottom-op">
      <a-button v-if="showStartUpBtn" type="primary" @click="handleStartUp">
        {{ $t("START_UP") }}
      </a-button>
      <a-button
        v-for="item in permissionBtns"
        :key="item.id"
        type="primary"
        @click="() => handleBtnOp(item)"
      >
        {{ item.customName || item.defaultName }}
      </a-button>
      <a-button type="primary" @click="() => (trackVisible = true)">
        {{ $t("PROCESS_TRACKING") }}
      </a-button>
      <a-button @click="goBack">
        <Icon type="icon-dir-f-rollback" :size="18" />
        {{ $t("BACK") }}
      </a-button>
    </div>
    <!-- 候选人 -->
    <SelectCandidate
      :key="key"
      :visible.sync="showCandicate"
      :params="{ taskId, type: 'user' }"
      :url="candidateConfig.url"
      :multiple="candidateConfig.multiple"
      :required-comment="requiredComment"
      @confirm="handleCandicateConfirm"
      @cancel="handleHideCandicate"
    />
    <!-- 流程追踪 -->
    <BpmnTrack
      :track-visible.sync="trackVisible"
      :is-call-xml-data="false"
      :default-xml-data="xmlData"
      :params="params"
    />
    <!-- 原因 -->
    <MegaModal
      width="416px"
      :title="reasonTitle"
      :visible.sync="showReason"
      @cancel="handleHideResson"
      @ok="handleRessonConfirm"
    >
      <a-form-model ref="ruleForm" :model="form">
        <a-form-model-item
          prop="comment"
          :label="$t('OPINION')"
          :rules="{
            required: requiredComment,
            message: $t('PLACEENTER'),
            trigger: 'blur',
          }"
        >
          <a-textarea
            v-model="form.comment"
            allow-clear
            :placeholder="$t('PLACEENTER')"
          />
        </a-form-model-item>
      </a-form-model>
    </MegaModal>
  </div>
</template>

<script>
import { Modal as MegaModal, Icon } from "@mega-design/ui-vue";
import ApiConstant from "@/api/ApiConstant";
import BpmnReadonly from "@/components/bpmn/readonly";
import BpmnForm from "@/components/bpmn/form/index";
import BpmnTrack from "@/components/bpmn/track";
import SelectCandidate from "@/components/SelectCandidate";

export default {
  components: {
    BpmnReadonly,
    BpmnForm,
    SelectCandidate,
    MegaModal,
    BpmnTrack,
    Icon,
  },
  data() {
    return {
      key: "init",
      formBusinessId: null,
      formData: [],

      typeList: [],
      approveTableColumns: [
        {
          dataIndex: "taskName",
          sorter: false,
          ellipsis: true,
          width: 180,
          title: () => this.$t("NODE"), // 节点
        },
        {
          dataIndex: "realName",
          sorter: false,
          ellipsis: true,
          width: 180,
          title: () => this.$t("HANDLER"), // 处理人
        },
        {
          dataIndex: "typeText",
          sorter: false,
          ellipsis: true,
          width: 180,
          title: () => this.$t("DEAL_METHOD"), // 处理方式
        },
        {
          dataIndex: "duration",
          sorter: false,
          ellipsis: true,
          width: 180,
          title: () => this.$t("DEAL_TIME"), // 处理时间
        },
        {
          dataIndex: "message",
          sorter: false,
          ellipsis: true,
          width: 180,
          title: () => this.$t("HANDLE_TIP"), // 处理意见
        },
      ],
      approveTableData: [],
      xmlData: {},

      showCandicate: false,

      showReason: false, // 意见modal
      form: {
        comment: undefined,
      },

      trackVisible: false, // 流程追踪modal

      permissionBtns: [],
      btnOpName: undefined,
      requiredComment: false,
    };
  },
  computed: {
    reasonTitle() {
      switch (this.btnOpName) {
        case "退回申请人":
          return this.$t("RETURN_TO_APPLICANT");
        case "驳回": // 驳回<->退回上一步
          return this.$t("TURN_DORN");
        case "撤回":
          return this.$t("WITHDRAW");
        default:
          // 办理
          return this.$t("DISPOSE_OF");
      }
    },
    // 找当前formCode
    currentForm() {
      return this.formData.find((item) => item.isCurrent);
    },
    params() {
      const { id, type } = this.$route.query;
      return { id, type };
    },
    taskId() {
      const { taskId } = this.$route.query;
      return taskId || this.xmlData.runningTaskId;
    },
    showStartUpBtn() {
      return !!(this.formData.length === 1 && !this.formData[0].formBusinessId);
    },
    candidateConfig() {
      const isDeal = this.btnOpName === "办理";
      return {
        url: isDeal
          ? `${ApiConstant.PREFIX_CORE}/api/flowable/task/candidate`
          : `${ApiConstant.PREFIX_CORE}/api/flowable/task/candidate-current`,
        multiple: isDeal,
        isDeal,
      };
    },
  },
  watch: {
    params: {
      handler() {
        if (Object.keys(this.params).length) {
          this.queryDetail();
        }
      },
      deep: true,
    },
  },
  async created() {
    try {
      await this.beforeSearch();
      this.queryDetail();
    } catch (err) {}
  },
  methods: {
    beforeSearch() {
      return this.getDictByCode("DIC:WORKFLOW:COMMENT_TYPE").then((res) => {
        this.typeList = res.data.data;
      });
    },
    queryDetail() {
      // form表单
      this.$axios
        .get(`${ApiConstant.PREFIX_CORE}/api/flowable/form/flowable-form`, {
          params: this.params,
        })
        .then((res) => {
          this.formData = res.data.data;
        });
      // 审核意见
      this.$axios
        .get(
          `${ApiConstant.PREFIX_CORE}/api/flowable/comment/list/${this.params.id}`,
          {
            params: this.params,
          }
        )
        .then((res) => {
          this.approveTableData = res.data.data.map((item) => ({
            ...item,
            typeText: this.getAttrValue(this.typeList, item.type),
          }));
        });
      // xml数据
      this.$axios
        .get(`${ApiConstant.PREFIX_CORE}/api/flowable/task/image-xml`, {
          params: this.params,
        })
        .then((res) => {
          this.xmlData = res.data.data;

          // 获取当前步骤的按钮
          if (this.taskId) {
            this.$axios
              .get(
                `${ApiConstant.PREFIX_CORE}/api/permission/task-permission`,
                {
                  params: {
                    taskId: this.taskId,
                  },
                }
              )
              .then((permissionRes) => {
                this.permissionBtns = permissionRes.data.data;
              });
          } else {
            this.permissionBtns = [];
          }
        });
    },
    getBpmnComponent() {
      return this.$refs[`${this.currentForm?.formCode}BpmnFormBlock`]?.[0]
        ?.$refs?.Component;
    },
    handleGetReq(selectedKeys, selectedRows, { comment } = {}) {
      const component = this.getBpmnComponent();
      const data = {
        [this.candidateConfig.isDeal ? "candidateUsers" : "userId"]:
          selectedKeys?.join(),
      };
      if (this.currentForm) {
        return {
          ...data,
          taskId: this.taskId,
          formBusinessId:
            this.currentForm.formBusinessId || this.formBusinessId,
          formCode: this.currentForm.formCode,
          instanceId: this.params.id,
          comment, // 任务意见
          values: component?.request || component?.form,
        };
      }
      return {
        ...data,
        comment,
        taskId: this.taskId,
        instanceId: this.params.id,
      };
    },
    handleStartUp() {
      const component = this.getBpmnComponent();
      const confirm = component?.confirm;
      if (typeof confirm === "function") {
        confirm().then((res1) => {
          const { data: formBusinessId } = res1.data;
          const { deployId } = this.$route.query;
          const variables = component?.request || component?.form;
          this.formBusinessId = formBusinessId;
          if (this.currentForm) {
            this.$axios
              .post(`${ApiConstant.PREFIX_CORE}/api/flowable/instance/start`, {
                formBusinessId,
                formCode: this.currentForm.formCode,
                procDefId: deployId,
                variables,
              })
              .then(() => {
                this.$message.success(this.$t("SUCCEEDED"));
                this.$router.push({
                  path: "/flowable/todo",
                });
                this.key = "start-up-success";
              });
          }
        });
      }
    },
    handleOpenCandicate() {
      this.showCandicate = true;
    },
    handleHideCandicate() {
      this.showCandicate = false;
    },
    handleCandicateConfirm(...args) {
      switch (this.btnOpName) {
        case "办理":
          this.handleDealAxios(...args);
          break;
        case "委派": // 委托<->委派
          this.handleConsignAxios(...args);
          break;
        case "转办": // 转派<->转办
          this.handleAssignAxios(...args);
          break;
        default:
          break;
      }
    },
    handleOpenReason() {
      this.showReason = true;
      this.form.comment = undefined;
    },
    handleHideResson() {
      this.showReason = false;
    },
    handleRessonConfirm(...args) {
      this.$refs.ruleForm.validate((valid) => {
        if (valid) {
          switch (this.btnOpName) {
            case "办理":
              this.handleDealAxios(...args);
              break;
            case "驳回": // 驳回<->退回上一步
              this.handleToPreviousAxios(...args);
              break;
            case "退回申请人":
              this.handleToApplicantAxios(...args);
              break;
            case "撤回":
              this.handleRecallAxios(...args);
              break;
            default:
              break;
          }
        }
      });
    },
    handleBtnOp(item) {
      this.btnOpName = item.defaultName;
      this.requiredComment = item.needComment === "Y";
      this.key = item.id;
      switch (item.defaultName) {
        case "办理":
          this.handleDeal();
          break;
        case "撤回":
          this.handleRecall();
          break;
        case "委派": // 委托<->委派
          this.handleConsign();
          break;
        case "驳回": // 驳回<->退回上一步
          this.handleToPrevious();
          break;
        case "转办": // 转派<->转办
          this.handleAssign();
          break;
        case "退回申请人":
          this.handleToApplicant();
          break;
        default:
          break;
      }
    },
    // 处理
    handleDeal() {
      if (this.xmlData.isEnd) {
        this.handleOpenReason();
      } else {
        this.handleOpenCandicate();
      }
    },
    handleDealAxios(...args) {
      const p = [];
      if (this.currentForm) {
        const component = this.getBpmnComponent();
        const confirm = component?.confirm;
        if (typeof confirm === "function") {
          p.push(confirm());
        }
      }
      let req;
      if (this.xmlData.isEnd) {
        req = {
          comment: this.form.comment,
          taskId: this.taskId,
          instanceId: this.params.id,
        };
      } else {
        req = this.handleGetReq(...args);
      }
      Promise.all([
        ...p,
        this.$axios.post(
          `${ApiConstant.PREFIX_CORE}/api/flowable/task/complete`,
          req
        ),
      ]).then(() => {
        this.handleHideCandicate();
        this.handleHideResson();
        this.$message.success(this.$t("SUCCEEDED"));
        this.key = "deal-success";
        this.queryDetail();
      });
    },
    // 撤回
    handleRecall() {
      this.handleOpenReason();
    },
    handleRecallAxios() {
      this.$axios
        .post(`${ApiConstant.PREFIX_CORE}/api/flowable/task/revoke`, {
          comment: this.form.comment,
          taskId: this.taskId,
          instanceId: this.params.id,
        })
        .then(() => {
          this.handleHideResson();
          this.$message.success(this.$t("SUCCEEDED"));
          this.key = "recall-success";
          this.queryDetail();
        });
    },
    // 委托<->委派
    handleConsign() {
      this.handleOpenCandicate();
    },
    handleConsignAxios(...args) {
      this.$axios
        .post(
          `${ApiConstant.PREFIX_CORE}/api/flowable/task/delegate`,
          this.handleGetReq(...args)
        )
        .then((res) => {
          this.handleHideCandicate();
          this.$message.success(this.$t("SUCCEEDED"));
          this.key = "consign-success";
          this.queryDetail();
        });
    },
    // 转派<->转办
    handleAssign() {
      this.handleOpenCandicate();
    },
    handleAssignAxios(...args) {
      this.$axios
        .post(
          `${ApiConstant.PREFIX_CORE}/api/flowable/task/assign`,
          this.handleGetReq(...args)
        )
        .then((res) => {
          this.handleHideCandicate();
          this.$message.success(this.$t("SUCCEEDED"));
          this.key = "assign-success";
          this.queryDetail();
        });
    },
    // 退回申请人
    handleToApplicant() {
      this.handleOpenReason();
    },
    handleToApplicantAxios() {
      this.$axios
        .post(`${ApiConstant.PREFIX_CORE}/api/flowable/task/return-apply`, {
          comment: this.form.comment,
          taskId: this.taskId,
          instanceId: this.params.id,
        })
        .then(() => {
          this.handleHideResson();
          this.$message.success(this.$t("SUCCEEDED"));
          this.key = "to-applicant-success";
          this.queryDetail();
        });
    },
    // 驳回<->退回上一步
    handleToPrevious() {
      this.handleOpenReason();
    },
    handleToPreviousAxios() {
      this.$axios
        .post(`${ApiConstant.PREFIX_CORE}/api/flowable/task/reject`, {
          comment: this.form.comment,
          taskId: this.taskId,
          instanceId: this.params.id,
        })
        .then(() => {
          this.handleHideResson();
          this.$message.success(this.$t("SUCCEEDED"));
          this.key = "to-previous-success";
          this.queryDetail();
        });
    },
    goBack() {
      this.$store.dispatch("tagsView/jumpBeforeView", {
        to: { path: this.$route.query?.returnUrl || "/" },
        vm: this,
      });
    },
  },
};
</script>

<style lang="less" scoped>
.launch-add {
  /deep/ .mega-design-business-table {
    .mega-design-pro-table {
      padding: 0 0 14px;
    }
    .s-table-tool {
      margin-bottom: 0;
    }
  }
  /deep/ .flowable .ant-collapse-content-box {
    position: relative;
    height: 300px;
  }
}
</style>
