<template>
  <div class="container">
    <el-card
      :shadow="device === 'desktop' ? 'always' : 'never'"
      class="card"
      :style="{
        border: device === 'desktop' ? '' : 'none',
        background: device === 'desktop' ? '' : '#f7f8fa',
        'min-height': device === 'desktop' ? '' : '100vh',
      }"
    >
      <template #header>
        <p>{{ config.customModel ? config.customModel.name : "办理" }}</p>
      </template>

      <template>
        <div class="steps" v-if="!/\/detail/.test($route.path)">
          <el-steps :space="120" finish-status="success" align-center>
            <template v-if="!isFirstNode">
              <el-step
                v-for="step in config.logs"
                :title="step.node.name"
                :status="step.status !== -1 ? 'success' : 'error'"
                icon="el-icon-circle-check"
              ></el-step>
            </template>
            <el-step
              :title="node.name"
              status="finish"
              icon="el-icon-edit"
            ></el-step>
            <el-step
              icon="el-icon-right"
              status="wait"
            >
              <template #title>
                <div style="max-width: 180px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">
                  <span v-for="(nextNode, index) in ((node.nextNodes && node.nextNodes instanceof Array) ? node.nextNodes : [])">{{ index === 0 ? '' : ',' }}{{ nextNode.name }}</span>
                </div>
                <div v-if="node.nextNodes">（{{ node.nextNodes.length }}种流程）</div>
              </template>
            </el-step>
          </el-steps>

          <el-divider></el-divider>
        </div>

        <div style="margin-bottom: 10px;">
          <el-button type="primary" @click="execScript('write')">执行编辑js</el-button>
          <el-button type="primary" @click="execScript('read')">执行查看js</el-button>
        </div>

        <div class="form-container" id="print-content">
          <el-form :model="flowLinkForm" label-position="right" label-width="130px">
            <el-form-item label="out_pay_id">
              <el-input v-model="flowLinkForm.out_pay_id"></el-input>
            </el-form-item>
            <el-form-item label="out_away_id">
              <el-input v-model="flowLinkForm.out_away_id"></el-input>
            </el-form-item>
            <el-form-item label="out_contract_id">
              <el-input v-model="flowLinkForm.out_contract_id"></el-input>
            </el-form-item>
          </el-form>
          <DesktopForm
            :device="device"
            ref="desktopForm"
            :config="config"
            :is-first-node="isFirstNode"
            :sub-form="subConfig"
            :fields="fields"
            :original-form="form"
            :readable="readableFields"
            :writeable="writeableFields"
            :rules="{}"
            :sub-rules="{}"
            :script-content="scriptContent"
            :logs="config.logs"
          ></DesktopForm>
        </div>
      </template>

      <!--      审批日志-->
      <div v-if="/\/detail/.test($route.path)" style="margin-top: 10px">
        <div>流转记录</div>
        <vxe-table
          style="margin-top: 10px;"
          show-footer
          ref="table"
          stripe
          class="log-table-scroll"
          keep-source
          show-overflow
          :column-config="{ resizable: true }"
          :print-config="{}"
          :export-config="{}"
          :custom-config="{ mode: 'popup' }"
          :footer-data="footerData"
          :data="config.logs || []"
          @cell-dblclick="cellDblclickEvent"
        >
          <vxe-column
            type="seq"
            width="62"
            align="center"
            field="seq"
            title="编号"
          />
          <vxe-column
            width="140"
            title="节点名称"
            align="center"
            field="node.name"
            :formatter="({ cellValue }) => cellValue || '节点已调整'"
          ></vxe-column>
          <vxe-column
            width="80"
            align="center"
            title="办理状态"
            field="status"
            :formatter="({ cellValue }) => myStatus.get(cellValue)"
          >
            <template #default="{ row }">
              <el-tag
                size="mini"
                :type="statusColor.get(row.status)"
                effect="dark"
              >{{ myStatus.get(row.status) }}</el-tag
              >
            </template>
          </vxe-column>
          <vxe-column
            align="center"
            width="80"
            title="承办人员"
            field="user.name"
          ></vxe-column>
          <vxe-column
            align="center"
            width="200"
            title="流转时间"
            field="created_at"
            :formatter="
              ({ cellValue }) =>
                $moment(cellValue).format('YYYY年MM月DD日 HH:mm:ss')
            "
          ></vxe-column>
          <vxe-column
            min-width="200"
            header-align="center"
            title="退回原因"
            field="reason"
          ></vxe-column>
          <vxe-column
            align="center"
            width="200"
            title="办理时间"
            field="updated_at"
          >
            <template #default="{ row }">
              <span
                :style="{
                  color:
                    row.deadline &&
                    row.updated_at &&
                    $moment(row.updated_at).isAfter(
                      $moment(row.deadline).endOf('day')
                    )
                      ? 'red'
                      : '',
                }"
              >{{
                  $moment(row.updated_at).format("YYYY年MM月DD日 HH:mm:ss")
                }}</span
              >
            </template>
          </vxe-column>
          <vxe-column align="center" title="耗时" field="use_time" width="120">
            <template #default="{ row }">
              <span>{{ diffTime(row.updated_at, row.created_at) }}</span>
            </template>
          </vxe-column>
        </vxe-table>
      </div>

      <div class="btns" ref="btns">
        <el-button
          v-if="$route.query.flow_id"
          icon="el-icon-document-add"
          type="primary"
          size="small"
          @click="submit()"
        >确认</el-button
        >
      </div>
    </el-card>

    <el-backtop></el-backtop>
  </div>
</template>

<script>
import DesktopForm from "./DesktopForm.vue";
import MobileForm from "./MobileForm.vue";
import assign from "./components/assign.vue";
import { generateRandomString } from '@/utils'
import {
  create,
  deal,
  fieldConfig, flowList,
  preConfig,
  preDeal,
  updateNodeTime,
  view, save
} from "@/api/flow";
import { deepCopy } from "@/utils";
import { validation, validationName } from "@/utils/validate";
import { print } from "@/utils/print";
export default {
  components: {
    DesktopForm,
    MobileForm,
  },
  data() {
    return {
      printKey: 0,
      isShowRollback: false,
      isShowForward: false,
      isShowAssign: false,
      info: [],
      config: {},
      subConfig: new Map(),
      myStatus: new Map([
        [-2, "会签退回"],
        [-1, "退回"],
        [0, "办理中"],
        [1, "已完成"],
      ]),
      statusColor: new Map([
        [-2, "warning"],
        [-1, "warning"],
        [0, ""],
        [1, "success"],
      ]),
      flowLinkForm: {
        out_pay_id: '',
        out_away_id: '',
        out_contract_id: ''
      },

      form: {},
      result: {},
      fileList: {},
      subFileList: {},
      rules: {},
      subRules: {},
      flows: [],
      csrf_token: '',
      scriptContent: '',
    };
  },
  methods: {
    execScript(mode='write') {
      if (mode === 'write') {
        this.scriptContent = this.writeScriptContent
      } else if (mode === 'read') {
        this.scriptContent = this.readScriptContent
      }
    },
    // 处理url中default_json
    handleDefaultJSON() {
      try {
        if(!this.$route.query?.default_json) return
        const res = JSON.parse(this.$route.query?.default_json)
        console.log('default_json', res)
        for (let key in this.$route.query) {
          if(/^out_(.*)_id/.test(key)) {
            this.form[key] = this.$route.query[key]
          }
        }
        for (let key in res) {
          try {
            let jsonObj = JSON.parse(res[key]);
            if (this.form.hasOwnProperty(key)) {
              this.form[key] = jsonObj;
            }
          } catch (err) {
            if (this.form.hasOwnProperty(key)) {
              this.form[key] = res[key];
            }
          }
        }
      } catch (err) {
        console.error(err)
      }
    },
    async print(isLog=false) {
      const _this = this
      let customModelId = this.config.customModel.id || this.$route.query.module_id
      const modelRes = await fieldConfig(customModelId,true)
      let pickTemplate = 0
      const printTemplates = [{
        id: 0,
        name: '基础模版',
        print_format: modelRes.customModel.print_format
      },...modelRes.customModel.print_formats]
      const h = this.$createElement;
      await this.$msgbox({
        title: '打印模版选择',
        message: h('div',{
          class: 'print-template-radios',
          key: this.printKey++
        },[
          h('div',{
          },printTemplates.map(i => h('div',{
            style: {
              display: 'flex',
              'align-items': 'center',
              'margin-top': '4px',
            }
          },[
            h('span',{
              class: 'el-radio__input'
            },[
              h('span', {
                class: 'el-radio__inner custom-cursor-on-hover'
              }),
              h('input', {
                style: {
                  cursor: 'pointer',
                  opacity: 0,
                  position: 'absolute',
                  top: 0,
                  left: 0,
                  right: 0,
                  bottom: 0,
                  margin: 0
                },
                attrs: {
                  // 添加属性
                  type: "radio",
                  id: `print-radio-${i.id}`,
                  name: "Radio",
                  value: i.id,
                  checked: pickTemplate === i.id,
                },
                on: {
                  change: () => {
                    pickTemplate = i.id
                  }
                }
              })
            ]),
            h('label', {
              style: {
                flex: 1
              },
              attrs: {
                for: `print-radio-${i.id}`
              },
              class: 'el-radio__label',
            }, i.name)
          ])))
        ]),
        showCancelButton: true,
        confirmButtonText: '确定',
        cancelButtonText: '取消',
      })
      const printText = printTemplates.find(i => i.id === pickTemplate)?.print_format
      if(isLog) {
        const res = await this.$refs['table'].exportData({
          type: 'html',
          download: false
        })
        await print.bind(this)(printText, isLog, _this.config.flow, res.content)
      } else {
        await print.bind(this)(printText, isLog, _this.config.flow)
      }
    },

    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' ? [] : "");
            }
          }
        }
      });
      this.form['flow_title'] = this.config?.flow?.title ?? `${this.config.customModel.name}（${this.$store.getters.name} ${this.$moment().format('YYYY-MM-DD HH:mm')}）`
    },
    formatTime(time) {
      const days = parseInt(time / (1000 * 60 * 60 * 24));
      const hours = parseInt((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
      const minutes = parseInt((time % (1000 * 60 * 60)) / (1000 * 60));
      const seconds = (time % (1000 * 60)) / 1000;
      return `${days > 0 ? days + "天" : ""}${
        hours > 0 ? hours + "时" : ""
      }${minutes}分${seconds}秒`;
    },

    async getConfig() {
      const loading = this.$loading({
        lock: true,
        text: "拼命加载中",
        spinner: "el-icon-loading",
        background: "rgba(0, 0, 0, 0.8)",
      });
      if (this.$route.query.flow_id) {
        try {
          const res = await view(this.$route.query.flow_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);
          this.form = Object.assign({}, this.form);
          const { data } = res?.flow;
          this.flowLinkForm.out_contract_id = res?.flow?.out_contract_id;
          this.flowLinkForm.out_away_id = res?.flow?.out_away_id;
          this.flowLinkForm.out_pay_id = res?.flow?.out_pay_id;

          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 && data[key][0].hasOwnProperty('url')) {
                    this.form[key] = data[key].map(i => ({
                      name: i.original_name,
                      url: i.url,
                      response: i,
                      TYPE_FILE: 1
                    }))
                  } else {
                    this.form[key] = ''
                  }
                }
                this.form[key] = data[key];
              }
            }
          }
          loading.close();
        } catch (err) {
          console.error(err);
          this.$message.error("配置失败");
          loading.close();
        }
      }
    },

    async submit(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) => {
        let keys = Object.keys(form)
        keys.forEach(key => {
          if (form[key] instanceof Array) {
            if (form[key].length > 0) {
              if (form[key][0].hasOwnProperty('response')) {
                form[key] = form[key].map(i => i.response)
              } else {
                form[key].forEach(i => {
                  uploadHandler(i)
                })
              }
            } else {
              form[key] = ''
            }
          } else {
            if (form[key] === 'null' || form[key] === 'undefined') {
              form[key] = ''
            }
          }
        })
      }
      uploadHandler(copyForm)
      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]
        }
      }
      try {
        if (this.$route.query.flow_id) {
          copyForm.id = this.$route.query.flow_id;
          const { flow, is_last_handled_log } = await save(
            this.$route.query.flow_id,
            Object.assign(copyForm, this.flowLinkForm)
          );
          this.result = flow;
          this.$message.success("操作成功")
        }
      } catch (err) {
        console.error(err);
      }
    },

    async cellDblclickEvent({ row, column }) {
      // if(this.$store.state.user.username !== 'admin') return
      if(column.field === 'created_at' || column.field === 'updated_at') {
        this.$prompt('请输入时间', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          inputPattern:  /^(?:19|20)[0-9][0-9]-(?:(?:0[1-9])|(?:1[0-2]))-(?:(?:[0-2][1-9])|(?:[1-3][0-1])) (?:(?:[0-2][0-3])|(?:[0-1][0-9])):[0-5][0-9]:[0-5][0-9]$/,
          inputErrorMessage: '时间格式不正确'
        }).then(({ value }) => {
          updateNodeTime({
            id: row.id,
            date: value,
            date_type: column.field
          }).then(_ => {
            this.$message.success('更新成功')
            this.getConfig()
          })
        })
      }
    },
  },
  computed: {
    device() {
      return this.$store.state.app.device;
    },
    fields() {
      return this.config?.customModel?.fields || [];
    },
    readableFields() {
      return /\/detail/.test(this.$route.path)
        ? this.fields?.map((i) => i.id)
        : this.config?.currentNode?.readable || [];
    },
    writeableFields() {
      return this.fields?.map(i => i.id) || [];
    },
    node() {
      return this.config?.currentNode || {};
    },
    writeScriptContent() {
      return this.config?.customModel?.js;
    },
    readScriptContent() {
      return this.config?.customModel?.view_js;
    },
    diffTime() {
      return function (end, start) {
        const diff = this.$moment(end).diff(this.$moment(start));
        return this.formatTime(diff);
      };
    },
    footerData() {
      const diff = this.$moment(this.config?.logs?.at(-1)?.updated_at).diff(
        this.$moment(this.config?.logs?.at(0)?.created_at)
      );
      return [
        {
          seq: "总耗时",
          use_time: this.formatTime(diff),
        },
      ];
    },
    isFirstNode() {
      return this.config?.logs?.length === 0 || this.config?.currentNode?.category === 'start' || this.$route.path === '/flow/edit'
    }
  },
  created() {
    this.getConfig();
  },
  mounted() {},
};
</script>

<style scoped lang="scss">
::v-deep .el-step__title {
  font-size: 14px;
  line-height: 1.5;
}
::v-deep .el-step__icon.is-icon {
  border-radius: 100%;
  box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
  width: 36px;
  height: 36px;
  border: solid 2px;
}
::v-deep .el-step.is-center .el-step__line {
  top: 50%;
}
::v-deep .el-card__header {
}
.container {
  padding: 20px;

  .card {
    position: relative;
  }
  .btns {
    display: flex;
    justify-content: center;
    margin-top: 10px;
    flex-wrap: wrap;
  }
}
.form-container {
}
@media (max-width: 768px) {
  .container {
    padding: 0;
  }
  .btns {
    justify-content: space-evenly;
    & > * {
      margin: 4px 6px;
    }
  }

  ::v-deep .el-steps--horizontal {
    display: flex;
    flex-wrap: wrap;
  }
}
</style>
<style lang="scss">
.log-table-scroll {
  ::-webkit-scrollbar {
    height: 0;
  }
}
.print-template-radios .el-radio__input:has(input[type=radio]:checked) .el-radio__inner {
  border-color: var(--theme-color);
  background: var(--theme-color);
  &::after {
    transform: translate(-50%,-50%) scale(1);
  }
}
</style>
