<template>
  <div>
    <vxe-modal
      title="批量审批"
      :z-index="zIndex"
      :value="isShow"
      @input="e => $emit('update:isShow', e)"
      :min-height="300"
      resize
      :width="defaultModalSize.sWidth"
      :height="defaultModalSize.sHeight"
      :fullscreen="$store.getters.device === 'mobile'"
      show-zoom
      draggable
      storage
      show-footer
    >
      <div v-if="isValidDone" style="margin-bottom: 10px;">
        <div style="color: #606266;font-weight: 600;font-size: 14px;line-height: 2;">可批量办理流程分组</div>

        <div>
          <el-tag style="margin-right: 4px;" v-for="(value, key) in batchData" :key="key">
            流水号：{{ tagFlowId(value) }}
          </el-tag>
        </div>
      </div>
      <vxe-table
        ref="table"
        stripe
        keep-source
        :column-config="{ resizable: true }"
        :print-config="{}"
        :export-config="{}"
        :row-config="{ keyField: 'id' }"
        :custom-config="{ mode: 'popup' }"
        :data="dealFlows"
        :checkbox-config="{
          checkMethod: ({ row }) => {
            return isValidDone
          }
        }"
      >
        <vxe-column
          type="checkbox"
          width="50"
          align="center"
          ></vxe-column>
        <vxe-column
          min-width="140"
          header-align="center"
          field="title"
          title="工作名称"
          show-overflow
        ></vxe-column>
        <vxe-column
          width="80"
          align="center"
          field="id"
          title="流水号"
        ></vxe-column>
        <vxe-column
          header-align="center"
          min-width="240"
          field="_simple"
          title="简要"
        ></vxe-column>
        <vxe-column
          width="80"
          title="发起人"
          align="center"
          field="creator.name"
        ></vxe-column>
        <vxe-column
          width="80"
          title="承办人员"
          align="center"
          field="last_log.user.name"
        ></vxe-column>
        <vxe-column
          header-align="center"
          min-width="120"
          field="custom_model.name"
          title="流程名称"
        ></vxe-column>
        <vxe-column
          width="164"
          field="no"
          align="center"
          title="编号"
        ></vxe-column>
        <vxe-column
          width="200"
          :visible="$route.params.type === 'all'"
          align="center"
          field="created_at"
          title="发起日期"
          :formatter="
                ({ cellValue }) =>
                  $moment(cellValue).format('YYYY-MM-DD HH:mm:ss')
              "
          :export-method="
                ({ row, column, options }) =>
                  $moment(row['created_at']).format('YYYY-MM-DD HH:mm:ss')
              "
        ></vxe-column>
      </vxe-table>
      <template>
        <DesktopForm
          :device="device"
          ref="desktopForm"
          :config="config"
          :is-first-node="isFirstNode"
          :need-flow-title="false"
          :sub-form="subConfig"
          :fields="fields"
          :original-form="form"
          :readable="[]"
          :script-content="scriptContent"
          :writeable="writeableFields"
          :rules="rules"
          :sub-rules="subRules"
          :logs="config.logs"
        ></DesktopForm>
      </template>
      <template #footer>
        <el-button
          icon="el-icon-document-add"
          type="info"
          size="small"
          @click="saveData('only-submit')"
        >暂存不流转</el-button
        >
        <el-button v-if="!isValidDone" type="primary" size="small" @click="saveData('assign')"
        >检查流转 <i class="el-icon-s-check"></i
        ></el-button>
        <el-button v-else type="primary" size="small" @click="submit('assign')"
        >保存并流转 <i class="el-icon-right"></i
        ></el-button>
      </template>
    </vxe-modal>

    <assign :visible.sync="isShowAssign" multiple :multipleIds="pickRowIds" @refresh="$emit('update:isShow', false),$emit('refresh')" />
  </div>
</template>

<script>
import { PopupManager } from 'element-ui/lib/utils/popup'
import { defaultModalSize } from '@/settings'
import { create, deal, fieldConfig, preDeal, getNextNodeBatch } from '@/api/flow'
import { validation, validationName } from "@/utils/validate";
import DesktopForm from "@/views/flow/DesktopForm.vue";
import assign from './assign.vue'
import { deepCopy } from "@/utils";
export default {
  components: {
    DesktopForm,assign
  },
  props: {
    isShow: {
      type: Boolean,
      default: false
    },
    dealFlows: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      loading: false,
      defaultModalSize,
      zIndex: PopupManager.nextZIndex(),

      form: {},
      subConfig: new Map(),
      config: {},
      rules: {},
      subRules: {},
      flows: [],

      isShowAssign: false,

      batchData: null,
      isValidDone: false,
      pickRowIds: []
    }
  },
  methods: {
    generateForm(object, fields, relation = false, pname) {
      fields.forEach((field) => {
        if (field.rules && field.rules.length > 0 && this.writeableFields.find(i => i === field.id) && !relation) {
          this.rules[field.name] = field.rules.map((rule) => {
            switch (rule) {
              case "required":
                if (field.type === 'relation') {
                  return {
                    validator: (myRule, value, callback) => {
                      if (value instanceof Array && value.length > 0) {
                        callback()
                      } else {
                        callback(`请填写${field.label}`)
                      }
                    },
                    message: `请填写${field.label}`,
                    trigger: "blur",
                  };
                } else {
                  return {
                    required: true,
                    message: `请填写${field.label}`,
                    trigger: "blur",
                  };
                }
              default:
                return {
                  validator: (myRule, value, callback) => {
                    if (validation.get(rule).test(value) || value === '') {
                      callback();
                    } else {
                      callback(
                        new Error(
                          `${field.label}必须为${validationName.get(rule)}`
                        )
                      );
                    }
                  },
                  trigger: "blur",
                  pattern: validation.get(rule),
                  message: `${field.label}必须为${validationName.get(rule)}`,
                };
            }
          });
        }
        if (relation) {
          this.subRules[`${pname}_rules`][field.name] = field.rules.map((rule) => {
            switch (rule) {
              case "required":
                return {
                  required: true,
                  message: `请填写${field.label}`,
                };
              default:
                return {
                  validator: ({ cellValue }) => {
                    return new Promise((resolve, reject) => {
                      if (validation.get(rule).test(cellValue) || cellValue === '') {
                        resolve()
                      } else {
                        reject(
                          new Error(
                            `${field.label}必须为${validationName.get(rule)}`
                          )
                        );
                      }
                    })
                  },
                  trigger: "blur",
                  pattern: validation.get(rule),
                  message: `${field.label}必须为${validationName.get(rule)}`,
                };
            }
          });
        }
        if (field.type === "relation") {
          this.subRules[`${field.name}_rules`] = {}
          object[field.name] = [{}];

          this.generateForm(
            object[field.name][0],
            this.subConfig.get(field.sub_custom_model_id)?.customModel?.fields,
            true,
            field.name
          );
        } else {
          if (/\/detail/.test(this.$route.path) && this.$route.query.flow_id) {
            object[field.name] = "";
          } else {
            if (this.writeableFields.indexOf(field.id) !== -1 || this.readableFields.indexOf(field.id) !== -1) {
              object[field.name] = (this.writeableFields.indexOf(field.id) !== -1 && field.default_value) ? field.default_value : (field.type === 'file' ? [] : "");
            }
          }
        }
      });
    },

    async getConfig() {
      const firstFlow = this.dealFlows[0]
      const loading = this.$loading({
        lock: true,
        text: "拼命加载中",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.8)",
      });
      try {
        const res = await preDeal(firstFlow.id);
        const { fields } = res?.customModel;
        let subFormRequest = [];
        const getSubForm = (id) => {
          subFormRequest.push(fieldConfig(id));
        };
        fields.forEach((field) => {
          if (field.sub_custom_model_id) {
            getSubForm(field.sub_custom_model_id);
          }
        });
        const subConfigs = await Promise.all(subFormRequest);
        subConfigs.forEach((sub) => {
          if (sub.customModel?.id) {
            this.subConfig.set(sub.customModel?.id, sub);
          }
        });
        this.config = res;
        this.generateForm(this.form, fields);
        const { data } = res?.flow;
        for (let key in data) {
          try {
            let jsonObj = JSON.parse(data[key]);
            jsonObj.forEach(item => {
              // 遍历对象中的每个键值对
              for (const key in item) {
                if (typeof item[key] === 'string') {
                  try {
                    // 尝试解析字符串为 JSON 对象
                    const parsedValue = JSON.parse(item[key]);
                    // 如果解析成功，替换原始字符串
                    item[key] = parsedValue;
                  } catch (e) {
                    // 如果解析失败，继续保持原始字符串
                  }
                }
              }
            })
            if (this.form.hasOwnProperty(key)) {
              this.form[key] = jsonObj;
            }
          } catch (err) {
            if (this.form.hasOwnProperty(key)) {
              if (data[key] instanceof Array) {
                if (data[key].length > 0) {
                  this.form[key] = data[key];
                } else {
                  this.form[key] = ''
                }
              }
              if (data[key] && data[key] !== 'null' && data[key] !== 'undefined') {
                this.form[key] = data[key];
              }
            }
          }
        }
        this.form = Object.assign({}, this.form);
        loading.close();
      } catch (err) {
        console.error(err);
        this.$message.error("配置失败");
        loading.close();
      }
    },

    async validFlow() {
      let loading;
      try {
        loading = this.$loading({
          lock: true,
          text: "验证是否能批量审批",
          spinner: "el-icon-loading",
          background: "rgba(0, 0, 0, 0.8)",
        });
        const { list } = await getNextNodeBatch({
          ids: this.dealFlows.map(i => i.id).toString()
        })
        this.batchData = {}
        list?.forEach((item, index) => {
          let nextNodeIds = item.current_node?.nextNodes?.sort((a, b) => a.id - b.id)?.map(j => j.id)?.toString()
          if (this.batchData.hasOwnProperty(nextNodeIds)) {
            this.batchData[nextNodeIds].push({
              data: item.flow_id,
              trend: item.is_trend
            })
          } else {
            Object.defineProperty(this.batchData, nextNodeIds, {
              value: [{
                data: item.flow_id,
                trend: item.is_trend
              }],
              enumerable: true,
              writable: true,
              configurable: false
            })
          }
        })
        this.isValidDone = true
        let longerData = Object.values(this.batchData).reduce((pre, cur) => (pre.length >= cur.filter(j => !j.trend)?.length) ? pre : cur.map(j => j.data), [])
        this.$refs['table']?.setCheckboxRow(this.dealFlows.filter(flow => longerData.indexOf(flow.id) !== -1), true)
      } catch (err) {
        console.error(err)
      } finally {
        loading.close()
      }
    },
    async saveData(type) {
      if (window.$_uploading) {
        this.$message.warning("文件正在上传中")
        return
      }
      let copyForm;
      try {
        await this.$refs['desktopForm'].validate()
      } catch (err) {
        console.warn(err)
        this.$message.warning('数据校验失败')
        return
      }
      copyForm = deepCopy(this.$refs["desktopForm"].form);
      const uploadHandler = (form, fields) => {
        let keys = Object.keys(form)
        keys.forEach(key => {
          if (form[key] instanceof Array) {
            if (form[key].length > 0 && typeof form[key][0] === 'object') {
              const myField = fields.find(field => field.name === key)
              if (myField) {
                if (myField.type === 'file') {
                  form[key] = form[key].map(i => i.hasOwnProperty('response') ? i.response : i)
                } else {
                  form[key].forEach(i => {
                    uploadHandler(i, this.subConfig.get(myField.sub_custom_model_id)?.customModel?.fields)
                  })
                }
              }
            } else {
              form[key] = ''
            }
          } else {
            if (form[key] === 'null' || form[key] === 'undefined') {
              form[key] = ''
            }
          }
        })
      }
      uploadHandler(copyForm, this.fields)
      for (let key in copyForm) {
        let myField = this.fields.find(i => i.name === key)
        if (myField && this.writeableFields.indexOf(myField.id) === -1) {
          delete copyForm[key]
        }
      }
      copyForm["current_node_id"] = this.config.currentNode.id;
      try {
        let callback = () => {}
        switch (type) {
          case "only-submit":
            copyForm["temporary_save"] = 1;
            callback = () => {
              this.$emit('update:isShow', false)
              this.$emit('refresh')
            }
            break;
          case "assign":
            copyForm["temporary_save"] = 0;
            callback = () => {
              this.validFlow()
            }
            break;
        }

        const resArr = await Promise.all(this.dealFlows.map(flow => deal(flow.id, copyForm)))
        const { flow, is_last_handled_log } = resArr[0]
        if (!is_last_handled_log) {
          await this.$alert(
            "办理成功，其他会签办理完成后，由最后办理的成员流转到下一节点。",
            "提示",
            {
              showClose: false,
            }
          );
          callback = () => {
            this.$emit('update:isShow', false)
            this.$emit('refresh')
          }
        }
        callback()
      } catch (err) {
        console.error(err);
      }
    },
    async submit() {
      function areAllElementsInArray(subsetArray, mainArray) {
        return subsetArray.every(element => mainArray.includes(element));
      }
      this.pickRowIds = this.$refs['table']?.getCheckboxRecords(true)?.map(i => i.id)
      console.log(345, this.pickRowIds)
      let groupAllowIds = Object.values(this.batchData)?.map(group => {
        return group.filter(j => !j.trend).map(j => j.data)
      })
      for(let i = 0;i < groupAllowIds.length;i++) {
        const group = groupAllowIds[i]
        if (areAllElementsInArray(this.pickRowIds, group)) {
          this.isShowAssign = true
          return
        }
      }
      this.$message.warning("存在不符合批量流转流程")
    },
  },
  computed: {
    device() {
      return this.$store.state.app.device;
    },
    fields() {
      return this.config?.customModel?.fields || [];
    },
    scriptContent() {
      if (this.config?.customModel?.view_js && this.$route.query.flow_id && /\/detail/.test(this.$route.path)) {
        return this.config?.customModel?.view_js;
      } else if (this.config?.customModel?.js && !/\/detail/.test(this.$route.path)) {
        return this.config?.customModel?.js;
      }
    },
    readableFields() {
      return []
    },
    writeableFields() {
      return this.config?.currentNode?.writeable || [];
    },
    isFirstNode() {
      return this.config?.logs?.length === 0 || this.config?.currentNode?.category === 'start'
    },
    tagFlowId() {
      return function (data) {
        return data?.filter(i => !i.trend)?.map(i => i.data)?.toString()
      }
    }
  },
  watch: {
    isShow(newVal) {
      if (newVal) {
        this.zIndex = PopupManager.nextZIndex()

        if (this.dealFlows instanceof Array && this.dealFlows.length > 0) {
          this.getConfig()
        }
      } else {
        this.batchData =  null
        this.isValidDone = false
        this.pickRowIds.length = 0
      }
    }
  }
}
</script>

<style scoped lang="scss">
</style>
