<template>
  <div :class="prefixCls">
    <ALayoutContent class="m-10">
      <h4 class="text-center text-lg pb-2">{{ state.formTitle }}</h4>
      <ATable v-model:activeKey="state.taskSelectedTab"
              class="bg-white"
              :tab-bar-style="{ 'padding-left': '13px' }"
      >
        <ATabPane key="formInfo">
          <template #tab>
            <span>
              <Icon icon="fa6-solid:file-lines"/>表单信息
            </span>
          </template>
          <!-- 动态表单:内置使用枇杷表单设计器 -->
          <workflow-preview-form v-if="state.formType !== '2'"
                                 ref="form"
                                 :taskFormData="state.taskFormData"
          />
          <!-- 外置表单:内置使用用户自定义的vue页面,手动填写页面路径即可 -->
          <component :is="state.formPath"
                     v-if="state.formType === '2'"
                     ref="form"
                     :formReadOnly="state.formReadOnly"
                     :businessId="state.businessId"
          />
        </ATabPane>
        <ATabPane key="processChart">
          <template #tab>
            <span>
              <Icon icon="fa-solid:image"/>流程图
            </span>
          </template>
        </ATabPane>
      </ATable>
      <a-card v-if="!state.processInsId || state.taskId || state.status === 'reStart'" style="margin-top:10px;margin-bottom:66px;">
        <AForm
          ref="auditForm"
          :labelCol="{ style: { width: '90px' } }"
          :wrapperCol="{ style: { width: '100%' } }"
          :model="state.auditForm"
          :scrollToFirstError="true"
        >
          <ACol :span="16">
            <AFormItem v-if="!state.processInsId || state.status === 'reStart'" label="流程标题" name="formTitle">
              <a-input v-model:value="state.formTitle" placeholder="请输入流程标题"/>
            </AFormItem>
          </ACol>
          <ACol :span="16">
            <AFormItem v-if="state.taskId" label="审批信息" name="message">
              <ATextarea
                v-model:value="state.auditForm.message"
                placeholder="请输入审批意见"
                :rows="3"
                allowClear
              />
            </AFormItem>
          </ACol>
          <ACol :span="16">
            <AFormItem label=" " :colon="false" name="isCC">
              <a-checkbox v-model:checked="state.isCC">是否抄送</a-checkbox>
            </AFormItem>
          </ACol>
          <ACol :span="16">
            <AFormItem v-if="state.isCC"
                       label="抄送给"
                       name="userIds"
                       :rules="[{required: true, message: '用户不能为空', validateTrigger: 'blur'}]"
            >
              <a-select v-model:value="state.auditForm.userIds" allowClear/>
            </AFormItem>
          </ACol>
          <ACol :span="16">
            <AFormItem label=" " :colon="false" name="isAssign">
              <a-checkbox v-model:checked="state.isAssign">指定下一步处理者(不设置就使用默认处理人)</a-checkbox>
            </AFormItem>
          </ACol>
          <ACol :span="16">
            <AFormItem v-if="state.isAssign"
                       label="指定"
                       name="assignee"
                       :rules="[{required: true, message: '用户不能为空', validateTrigger: 'blur'}]"
            >
              <a-select v-model:value="state.auditForm.userIds" allowClear/>
            </AFormItem>
          </ACol>
        </AForm>
      </a-card>
    </ALayoutContent>
    <footer class="workflow-form__footer" :style="getWrapFormFooterStyle">
      <a-button size="large" type="primary">审批</a-button>
      <a-button size="large" type="primary" danger>驳回</a-button>
    </footer>
  </div>
</template>
<script lang="ts" setup>
  /**
   * 提供模板规范代码参考,请尽量保证编写代码风格跟模板规范代码一致
   * 采用vben-动态表格表单封装组件编写,采用 setup 写法
   * Copyright © 2023-2023 <a href="https://godolphinx.org">海豚生态开源社区</a> All rights reserved.
   * author wangxiang4
   */
  import { reactive, onActivated, unref, nextTick, ref, computed, CSSProperties } from 'vue';
  import { Input, LayoutContent, Tabs, Form, Col } from 'ant-design-vue';
  import type { FormProperty } from '/@/api/platform/workflow/entity/formProperty';
  import type { Workflow } from '/@/api/platform/workflow/entity/workflow';
  import type { WorkflowButton } from '/@/api/platform/workflow/extension/entity/workflowButton';
  import { useRouter } from 'vue-router';
  import { saveWorkflowCopy } from '/@/api/platform/workflow/extension/controller/workflowCopy';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { startProcessDefinition, stopProcessInstance, getFlowChart as getProcessDefFlowChart  } from '/@/api/platform/workflow/controller/process';
  import { useTabs } from '/@/hooks/web/useTabs';
  import { auditTask, rollBackTaskList, rejectTask, transferTask, delegateTask, getFlowChart, listHistoryFlowChange } from '/@/api/platform/workflow/controller/task';
  import { useModal } from '/@/components/Modal';
  import type { KiccUser } from '/@/api/common/base/entity';
  import WorkflowPreviewForm from './WorkflowPreviewForm.vue';
  import { getProcessStartEventFormData, getTaskFormData } from '/@/api/platform/workflow/controller/form';
  import { findByDefIdAndTaskId } from '/@/api/platform/workflow/extension/controller/activityExtensionData';
  import { useDesign } from '/@/hooks/web/useDesign';
  import { useAppInject } from '/@/hooks/web/useAppInject';
  import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';

  /** 类型规范统一声明定义区域 */
  interface WindowState {
    // 流程表单标题
    formTitle: string;
    // 流程表单key
    formKey: string;
    // 表单类型(1:动态表单,2:外置表单)
    formType: string;
    // 外置表单路径
    formPath: string;
    // 外置表单是否只读
    formReadOnly: boolean,
    // 外置表单业务数据绑定ID
    businessId: string,
    // 动态表单字段配置数据
    taskFormData: FormProperty[],

    // 设置选择任务选项卡
    taskSelectedTab: string,
    // 流程任务ID
    taskId: string,
    // 流程任务定义key
    taskDefKey: string,

    // 流程定义ID
    processDefId: string,
    // 流程实例ID
    processInsId: string,
    // 流程定义Key
    processDefKey: string,

    // 当前任务表单操作状态
    status: string,
    // 历史流转信息
    historyFlowChangeList: Workflow[],
    // 当前操作按钮配置信息
    buttons: Partial<WorkflowButton>[],
    // 是否抄送
    isCC: boolean,
    // 是否指定代理人
    isAssign: boolean,
    // 审批表单信息
    auditForm: {
      message: string,
      mesCode: string,
      mesName: string,
      // 抄送用户ID
      userIds: string,
      // 任务代理人ID
      assignee: string,
    },
  }

  /** 通用变量统一声明区域 */
  const ALayoutContent = LayoutContent;
  const ATable = Tabs;
  const ATabPane = Tabs.TabPane;
  const AForm = Form;
  const AFormItem = Form.Item;
  const ACol = Col;
  const ATextarea = Input.TextArea;

  const { prefixCls } = useDesign('task-form');
  const { getIsMobile } = useAppInject();
  const { getCalcContentWidth } = useMenuSetting();
  const state = reactive<WindowState>({
    formTitle: '',
    formKey: '',
    formType: '',
    formPath: '',
    formReadOnly: false,
    businessId: '',
    taskFormData: [],

    taskSelectedTab: 'formInfo',
    taskId: '',
    taskDefKey: '',

    processDefId: '',
    processInsId: '',
    processDefKey: '',

    status: '',
    historyFlowChangeList: [],
    buttons: [],
    isCC: false,
    isAssign: false,

    auditForm: {
      message: '',
      mesCode: '',
      mesName: '',
      userIds: '',
      assignee: ''
    }
  });
  const { currentRoute, push } = useRouter();
  const { params, query } = unref(currentRoute);
  const { notification, createMessage, createConfirm } = useMessage();
  const { close } = useTabs();
  const form = ref();
  const [registerUser , { openModal: openUser }] = useModal();
  const [registerRollBackTask , { openModal: openRollBackTask }] = useModal();
  onActivated(() => {
    handleInit();
    nextTick(async () => {
      // 获取流程图数据
      if (state.processInsId) {
        const data = await getFlowChart(state.processInsId);
        //this.$refs.flowableChart.setHighlightImportDiagram(response)
      } else {
        const data = getProcessDefFlowChart(state.processDefId);
        //this.$refs.flowableChart.setHighlightImportDiagram({ bpmnXml: data })
      }

      // 初始化外置表单
      if (state.formType === '2') {
        if (state.formKey === '/404') {
          state.formPath = '';
          createMessage.info('没有关联流程表单!');
        } else {
          state.formPath = require('@/views' + state.formKey + '.vue').default;
        }
      // 初始化动态表单
      } else {
        if (state.formKey === '/404') {
          form.value.init('');
        } else {
          form.value.init(state.formKey);
        }
        // 获取启动事件表单数据
        if (state.status === 'start' || state.status === 'reStart') {
          state.taskFormData = await getProcessStartEventFormData(state.processDefId);
          // 获取任务表单数据
        } else {
          state.taskFormData = await getTaskFormData(state.taskId);
        }
      }

      // 设置启动按钮配置
      if (state.status === 'start' || state.status === 'reStart') {
        state.buttons = [{ code: '_workflow_activity_start', name: '启动', isHide: '0' }];
      // 获取bpmn设计器按钮配置
      } else if (state.processDefKey && state.taskDefKey) {
        const data = await findByDefIdAndTaskId({ processDefId: state.processDefKey,  activityDefId: state.taskDefKey });
        state.buttons = data.workflowButtonList;
      }
      // 获取历史任务流转列表
      if (state.processInsId) {
        state.historyFlowChangeList = await listHistoryFlowChange(state.processInsId);
      }
    });
  });

  function handleInit() {
    state.taskSelectedTab = 'formInfo';
    state.processDefId = query.processDefId as string;
    state.processInsId = query.processInsId as string;
    state.processDefKey = query.processDefKey as string;
    state.formType = query.formType as string;
    state.formKey = query.formKey as string;
    state.taskId = query.taskId as string;
    state.taskDefKey = query.taskDefKey as string;
    state.status = query.status as string;
    state.formTitle = query.formTitle as string;
    state.businessId = query.businessId as string;
    state.formReadOnly = query.formReadOnly === 'true';
    state.isCC = false;
    state.isAssign = false;
    state.auditForm.assignee = '';
    state.auditForm.userIds = '';
    state.auditForm.message = '';
  }

  /** 流程抄送 */
  function cc(data: Recordable) {
    if (state.isCC && state.auditForm.userIds) {
      //this.$refs['auditForm'].validate((valid) => {
        //if (valid) {
          saveWorkflowCopy(state.auditForm.userIds, {
            processDefId: state.processDefId,
            processInsId: data.processInsId,
            processDefName: '',
            processInsName: state.formTitle,
            taskName: ''
          });
        //}
      //});
    }
  }

  /** 暂存草稿 */
  function save() {
    notification.warn({
      message: '提示',
      description: '功能正在开发中...'
    });
  }

  /** 启动流程 */
  function start(vars: Recordable) {
    // 外置表单
    if (state.formType === '2') {
      form.value.startProcessDefinition(async (businessTable: string, businessId: string) => {
        const processInsId = await startProcessDefinition({
          processDefKey: this.processDefKey,
          businessTable: businessTable,
          businessId: businessId,
          ...vars
        });
        await close();
        await push({path: '/workflow/task/index'});
        cc({ processInsId });
      });
    // 动态表单
    } else {
      form.value.startFormProcessDefinition({ processDefId: this.processDefId, ...vars }, (processInsId: string) => {
        close();
        push({ path: '/workflow/task/index' });
        cc({ processInsId });
      });
    }
  }

  /** 同意任务 */
  function agree(vars?: Recordable) {
    commit(vars);
  }

  /** 驳回任务 */
  function reject () {
    createConfirm({
      iconType: 'warning',
      title: '警告',
      content: '确定驳回任务吗?',
      onOk: async () => {
        const nodes = await rollBackTaskList(state.taskId);
        if (nodes.length > 0) {
          const backTaskDefKey = nodes[nodes.length - 1].taskDefKey;
          await handleRollBackTask(backTaskDefKey);
        }
      }
    });
  }

  /** 转办 */
  function transfer() {
    openUser(true,{ _tag: 'transfer' });
  }

  /** 委托 */
  function delegate () {
    openUser(true,{ _tag: 'delegate' });
  }

  /** 终止 */
  function stop() {
    createConfirm({
      iconType: 'warning',
      title: '警告',
      content: '确定终止流程吗?',
      onOk: async () => {
        await stopProcessInstance(this.processInsId, this.auditForm.message);
        await close();
        await push({path: '/workflow/task/index'});
        cc({processInsId: state.processInsId});
      }
    });
  }

  /** 打印 */
  function print() {
    console.warn('---工作流表单打印成功,此处可以做一些打印回调逻辑处理!---');
  }

  /** 驳回到任意节点 */
  function rollBack() {
    openRollBackTask(true,{ taskId: this.taskId });
  }

  /** 加签 */
  function addMultiInstance() {
    // flowable开源版加签会导致模板数量急剧扩大,需要经过内部讨论是否有比较好的解决方案:http://www.pangubpm.com/doc58.html
    notification.warn({
      message: '提示',
      description: '功能正在开发中...'
    });
  }

  /** 减签 */
  function delMultiInstance () {
    notification.warn({
      message: '提示',
      description: '功能正在开发中...'
    });
  }

  /** 自定义按钮提交 */
  function commit(vars?: Recordable) {
    // 外置表单审批
    if (state.formType === '2') {
      form.value.auditTask(async () => {
         await auditTask({
          taskId: this.taskId,
          taskDefKey: this.taskDefKey,
          processInsId: this.processInsId,
          processDefId: this.processDefId,
          activityCommentInfo: this.auditForm,
          assignee: this.auditForm.assignee,
          vars,
        });
        await close();
        await push({ path: '/workflow/task/index' });
        cc({ processInsId: state.processInsId });
      });
    // 动态表单审批
    } else {
      form.value.auditFormTask({
        taskId: this.taskId,
        processInsId: this.processInsId,
        activityCommentInfo: this.auditForm,
        assignee: this.auditForm.assignee,
        vars,
      }, () => {
        close();
        push({ path: '/workflow/task/index' });
        cc({ processInsId: state.processInsId });
      });
    }
  }

  /** 处理回退到任意节点 */
  async function handleRollBackTask(backTaskDefKey: string) {
    await rejectTask({
      currentTaskId: this.taskId,
      rollBackTaskDefKey: backTaskDefKey,
      comment: this.auditForm
    });
    await close();
    await push({ path: '/workflow/task/index' });
    cc({ processInsId: state.processInsId });
  }

  /** 处理转派任务 */
  async function handleTransferTask(userList: KiccUser[]) {
    await transferTask( this.taskId, userList[0].id);
    await close();
    await push({ path: '/workflow/task/index' });
    cc({ processInsId: state.processInsId });
  }

  /** 处理任务委派 */
  async function handleDelegateTask(userList: KiccUser[]) {
    await delegateTask(this.taskId, userList[0].id);
    await close();
    await push({ path: '/workflow/task/index' });
    cc({ processInsId: state.processInsId });
  }

  function submit(button: WorkflowButton) {
    // 设置流程变量
    const vars: Recordable = {};
    // 流程表单标题
    vars.title = state.formTitle;
    // 指定的下一步骤处理人
    vars.assignee = state.auditForm.assignee;
    // 操作类型
    state.auditForm.mesCode = button.code;
    // 操作名称
    state.auditForm.mesName = button.name;
    switch (button.code) {
        // 启动流程
      case '_workflow_activity_start':
        start(vars);
        break;
        // 保存草稿
      case '_workflow_activity_save':
        save();
        break;
        // 同意
      case '_workflow_activity_agree':
        agree();
        break;
        // 驳回
      case '_workflow_activity_reject':
        reject();
        break;
        // 驳回到任意步骤
      case '_workflow_activity_roll_back':
        rollBack();
        break;
        // 加签
      case '_workflow_activity_add_multi_instance':
        addMultiInstance();
        break;
        // 减签
      case '_workflow_activity_del_multi_instance':
        delMultiInstance();
        break;
        // 转办
      case '_workflow_activity_transfer':
        transfer();
        break;
        // 外派
      case '_workflow_activity_delegate':
        delegate();
        break;
        // 终止
      case '_workflow_activity_stop':
        stop();
        break;
        // 打印
      case '_workflow_activity_print':
        print();
        break;
        // 自定义按钮提交
      default:
        commit(vars);
    }
  }

  const getWrapFormFooterStyle = computed((): CSSProperties | Recordable => {
    return {
      width: unref(getIsMobile) ? '100%' : unref(getCalcContentWidth)
    };
  });

</script>
<style lang="less" scoped>
  @prefix-cls: ~'@{namespace}-task-form';

  .@{prefix-cls} {
    .workflow-form {
      &__footer{
        height: 66px;
        background: #fff;
        display: flex;
        gap: 11px;
        flex-flow: row nowrap;
        justify-content: center;
        align-items: center;
        -webkit-box-shadow: 0 -3px 5px 0 rgba(0,0,0,.12);
        box-shadow: 0 -3px 5px 0 rgba(0,0,0,.12);
        -webkit-transition: inline-block 0.3s, left 0.3s, width 0.3s, margin-left 0.3s, font-size 0.3s;
        transition: inline-block 0.3s, left 0.3s, width 0.3s, margin-left 0.3s, font-size 0.3s;
        position: fixed;
        bottom: 0;
        z-index: @page-footer-z-index;
      }
    }
  }

  .ant-form {
    .ant-form-item {
      margin-bottom: 15px;
    }
  }
</style>
