<template>
  <a-modal
    :title="title"
    :visible="visible"
    :width="650"
    destroy-on-close
    :mask-closable="false"
    :confirm-loading="importConfirmLoading"
    @ok="importConfirm"
    @cancel="visible = false"
  >
    <sd-form ref="importForm" :init-values="importFormData" :class="$style.warp">
      <template v-slot="{ model }">
        <a-row v-for="field in importFormData" :key="field.nme">
          <sd-form-item :name="field.name">
            <template v-if="field.dataType === 'attachment'">
              <a-upload-dragger
                name="file"
                :multiple="false"
                :custom-request="(file) => customRequest(file)"
                :file-list="fileList"
                :accept="field.attr.allowType ? field.attr.allowType : ''"
                @change="
                  (info) => {
                    handleChange(info, field.name)
                  }
                "
              >
                <p class="ant-upload-drag-icon">
                  <a-icon type="inbox" />
                </p>
                <p class="ant-upload-text">
                  点击或将文件拖拽到这里上传
                </p>
              </a-upload-dragger>
            </template>
            <template v-if="field.isOrgTree">
              <sd-value-picker
                v-model="model[field.name]"
                single
                option-value="key"
                option-label="title"
              >
                <template v-slot="scope">
                  <sd-picker-source-tree :load-tree-data="onLoadTreeData" v-bind="scope" />
                </template>
              </sd-value-picker>
            </template>
            <template v-if="['dep', 'user'].includes(field.importType)">
              <a-button
                type="link"
                size="small"
                :loading="downloadLoading[field.name]"
                @click="downloadTemplate(field)"
                >点击下载</a-button
              >
            </template>
          </sd-form-item>
        </a-row>
      </template>
    </sd-form>
    <a-modal
      :title="title"
      :visible="visibleTip"
      :width="650"
      destroy-on-close
      :confirm-loading="importTipConfirmLoading"
      @ok="importTipConfirm"
      @cancel="visibleTip = false"
    >
      导入角色用户策略:<a-radio-group v-model="conflictStrategy" :options="conflictStrategyOpts" />

      <div v-for="item in tipKeys" :key="item.id">
        <template v-if="tipData[item.id]">
          <template v-if="item.id === 'existRole'">
            <table :class="$style['act-table']">
              <thead>
                <tr>
                  <th :class="$style['column-title']">已存在角色</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(info, infoIndex) in tipData[item.id]" :key="info.name + infoIndex">
                  <td>{{ info.name.join(',') }}</td>
                </tr>
              </tbody>
            </table>
          </template>
          <template v-else>
            <table :class="$style['act-table']">
              <thead>
                <tr>
                  <th :class="$style['column-title']">{{
                    item.id === 'existRolesAndUsers'
                      ? '已存在角色'
                      : item.id === 'existRolesNoUsers'
                      ? '已存在角色'
                      : '不存在角色'
                  }}</th>
                  <th :class="$style['column-act']">{{
                    item.id === 'existRolesAndUsers'
                      ? '已存在用户'
                      : item.id === 'existRolesNoUsers'
                      ? '不存在用户'
                      : '不存在用户'
                  }}</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(info, infoIndex) in tipData[item.id]" :key="info.role + infoIndex">
                  <td>{{ info.role }}</td>
                  <td>{{ info.name.join(',') }}</td>
                </tr>
              </tbody>
            </table>
          </template>
        </template>
      </div>
    </a-modal>
  </a-modal>
</template>

<script>
import axios from '@/common/services/axios-instance'
import { Modal } from '@/common/one-ui'
import { message } from 'ant-design-vue'
import download from '@/common/services/download'
import OrgService from './org-service'
import components from './_import-components/sd-org-import-import'

export default {
  name: 'SdOrgImport',
  metaInfo: {
    title: 'SdOrgImport',
  },
  components,
  props: {
    importFormData: {
      type: Array,
      default: function() {
        return []
      },
    },
    bussinessId: {
      type: String,
      default: function() {
        return null
      },
    },
    processParam: {
      type: Function,
      default: undefined,
    },
    reqUrl: {
      type: String,
      default: function() {
        return null
      },
    },
    checkUrl: {
      type: String,
      default: function() {
        return null
      },
    },
    processCheckParam: {
      type: Function,
      default: undefined,
    },
  },
  data() {
    return {
      title: '',
      visible: false,
      fileList: [],
      importConfirmLoading: false,
      loadingMsg: null,

      visibletIP: false,
      importTipConfirmLoading: false,
      tipData: {},
      tipKeys: [
        { id: 'existRole', name: '已存在角色' },
        { id: 'unexistRoleAndUsers', name: '不存在角色' },
        { id: 'existRolesNoUsers', name: '存在角色不存在用户' },
        { id: 'existRolesAndUsers', name: '存在角色和用户' },
      ],

      conflictStrategy: '0',
      conflictStrategyOpts: [
        {
          label: '跳过导入角色用户',
          value: '0',
        },
        {
          label: '覆盖导入角色用户',
          value: '1',
        },
      ],
      visibleTip: false,
      downloadLoading: {},
    }
  },
  methods: {
    show(title) {
      this.title = title
      this.visible = true
      this.conflictStrategy = '0'
      this.fileList = []
    },
    customRequest(files, item) {
      if (files.file.size === 0) {
        message.warn(`不能上传大小为0的文件`)
        return
      }

      const formData = new FormData()
      formData.append('file', files.file)
      const url = 'api/framework/v1/tmp-file/upload'

      axios
        .post(url, formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        })
        .then((res) => {
          if (res.status === 200) {
            // files.file.status = 'done'
            files.onSuccess(res.data, files)
          } else {
            message.warn(`上传失败`)
          }
        })
        .catch((e) => {
          throw e
        })
    },
    handleChange(info, name) {
      let fileList = [...info.fileList]

      // 1. Limit the number of uploaded files
      //    Only to show two recent uploaded files, and old ones will be replaced by the new
      fileList = fileList.slice(-1)

      // 2. read from response and show file link
      fileList = fileList.map((file) => {
        if (file.response) {
          // Component will show file.url as link
          file.url = file.response.url
          file.id = parseInt(file.response.id, 10)
        }
        return file
      })

      this.$refs.importForm.setFieldValue(name, fileList)
      this.fileList = fileList
    },
    importTipConfirm() {
      this.importTipConfirmLoading = true
      this.importConfirm().then((res) => {
        this.importTipConfirmLoading = false
        this.visibleTip = false
      })
    },
    importConfirm() {
      return new Promise((resolve) => {
        this.$refs.importForm.validateFields().then((success) => {
          if (success) {
            let values = this.$refs.importForm.getFieldsValue()

            this.importFormData.forEach((item) => {
              if (item.dataType === 'attachment') {
                // 附件默认均取第一个
                values[item.name] = values[item.name][0].response
              }
            })

            if (this.bussinessId === 'role' && this.importTipConfirmLoading === false) {
              let checkValues
              if (this.processCheckParam) {
                checkValues = this.processCheckParam(values)
              }
              this.importConfirmLoading = true
              this.loadingMsg = message.loading({
                key: this.msgKey,
                content: '加载中...',
                duration: 0,
              })
              OrgService.importFileDataCheck(this.checkUrl, checkValues)
                .then((res) => {
                  if (res.status === 200) {
                    const ret = res.data
                    if (ret === null) {
                      message.error(res.data?.message || '导入失败')
                    } else if (
                      res.data.length >= 1 &&
                      (ret[0].existRole != null ||
                        ret[0].unexistRoleAndUsers != null ||
                        ret[0].existRolesNoUsers != null ||
                        ret[0].existRolesAndUsers != null)
                    ) {
                      this.tipData = {}
                      ret.forEach((item) => {
                        this.tipKeys.forEach((info) => {
                          if (item[info.id]) {
                            if (!this.tipData[info.id]) {
                              this.tipData[info.id] = []
                            }
                            const name = []
                            let role
                            if (info.id === 'existRole') {
                              for (const i in item[info.id]) {
                                name.push(i)
                              }
                              this.tipData[info.id].push({
                                name,
                              })
                            } else {
                              for (const i in item[info.id]) {
                                role = i
                                name.push(item[info.id][i])
                              }
                              this.tipData[info.id].push({
                                role,
                                name,
                              })
                            }
                          }
                        })
                      })

                      this.visibleTip = true
                    } else {
                      if (this.processParam) values = this.processParam(values)
                      // 系统中不存在重复的角色和用户，可以随意导入
                      OrgService.importFileData(this.reqUrl, values)
                        .then((res) => {
                          if (res.status === 200) {
                            this.loadingMsg?.()

                            if (this.fileList[0].response.name.endsWith('.gz')) {
                              if (Array.isArray(res.data) && res.data.length > 0) {
                                Modal.info({
                                  title: '处理明细',
                                  content: res.data.join('\n'),
                                  okText: '关闭',
                                  onOk: () => {
                                    this.visible = false
                                    this.$emit('feedback', true)
                                    resolve(true)
                                  },
                                })
                              } else {
                                message.success('导入成功')
                                this.visible = false
                                this.$emit('feedback', true)
                                resolve(true)
                              }
                            } else if (this.fileList[0].response.name.endsWith('.xls')) {
                              // 导入excel角色
                              const dispData = res.data
                                .map((item, index) => {
                                  if (!(item === '' || item === null)) {
                                    item =
                                      item +
                                      (index === 0
                                        ? '账户不存在'
                                        : index === 1
                                        ? '匹配失败'
                                        : '信息错误')
                                  }
                                  return item
                                })
                                .filter((item) => {
                                  return !(item === '' || item === null)
                                })
                              if (dispData.length === 0) {
                                message.success('导入成功')
                                this.visible = false
                                this.$emit('feedback', true)
                                resolve(true)
                              } else {
                                Modal.info({
                                  title: '处理明细',
                                  content: dispData.join('\n'),
                                  okText: '关闭',
                                  onOk: () => {
                                    this.visible = false
                                    this.$emit('feedback', true)
                                    resolve(true)
                                  },
                                })
                              }
                            }
                          } else {
                            message.error(res.data?.message || '导入失败')
                          }
                        })
                        .catch(() => message.error('导入失败'))
                        .finally(() => {
                          this.importConfirmLoading = false
                          this.loadingMsg?.()
                        })
                    }
                  } else {
                    message.error(res.data?.message || '导入失败')
                  }
                })
                .catch((error) => {
                  message.error(error.data?.message || '导入失败')
                })
                .finally(() => {
                  this.importConfirmLoading = false
                  this.loadingMsg?.()
                })
            } else {
              if (this.bussinessId === 'role') {
                values.conflictStrategy = parseInt(this.conflictStrategy, 10)
              }
              if (this.processParam) values = this.processParam(values)
              this.importConfirmLoading = true
              this.loadingMsg = message.loading({
                key: this.msgKey,
                content: '加载中...',
                duration: 0,
              })
              OrgService.importFileData(this.reqUrl, values)
                .then((res) => {
                  if (res.status === 200) {
                    this.loadingMsg?.()

                    if (
                      this.bussinessId === 'org' ||
                      (this.bussinessId === 'role' &&
                        this.fileList[0].response.name.endsWith('.gz'))
                    ) {
                      if (Array.isArray(res.data) && res.data.length > 0) {
                        Modal.info({
                          title: '处理明细',
                          content: res.data.join('\n'),
                          okText: '关闭',
                          onOk: () => {
                            this.visible = false
                            this.$emit('feedback', true)
                            resolve(true)
                          },
                        })
                      } else {
                        message.success('导入成功')
                        this.visible = false
                        this.$emit('feedback', true)
                        resolve(true)
                      }
                    } else if (
                      this.bussinessId === 'role' &&
                      this.fileList[0].response.name.endsWith('.xls')
                    ) {
                      // 导入excel角色
                      const dispData = res.data
                        .map((item, index) => {
                          if (!(item === '' || item === null)) {
                            item =
                              item +
                              (index === 0 ? '账户不存在' : index === 1 ? '匹配失败' : '信息错误')
                          }
                          return item
                        })
                        .filter((item) => {
                          return !(item === '' || item === null)
                        })
                      if (dispData.length === 0) {
                        message.success('导入成功')
                        this.visible = false
                        this.$emit('feedback', true)
                        resolve(true)
                      } else {
                        Modal.info({
                          title: '处理明细',
                          content: dispData.join('\n'),
                          okText: '关闭',
                          onOk: () => {
                            this.visible = false
                            this.$emit('feedback', true)
                            resolve(true)
                          },
                        })
                      }
                    } else {
                      Modal.info({
                        title: '处理明细',
                        content: res.data.join('\n'),
                        okText: '关闭',
                        onOk: () => {
                          this.visible = false
                          this.$emit('feedback', true)
                          resolve(true)
                        },
                      })
                    }
                  } else {
                    message.error(res.data?.message || '导入失败')
                  }
                })
                .catch(() => message.error('导入失败'))
                .finally(() => {
                  this.importConfirmLoading = false
                  this.loadingMsg?.()
                })
            }
          }
        })
      })
    },
    onLoadTreeData(parentCatId, parentCatObj) {
      return new Promise((resolve) => {
        if (parentCatId) {
          return OrgService.getOrgDepTree({ id: parentCatId }).then((deps) => {
            resolve(this.parseTreeData(deps.data))
          })
        } else {
          return OrgService.getOrgDepRoot().then((roots) => {
            resolve(this.parseTreeData(roots.data))
          })
        }
      })
    },
    parseTreeData(deps) {
      return deps.map((dep) => {
        return {
          key: dep.id,
          title: dep?.props?.hierarchical === 'true' ? dep.text + '(已开启分级)' : dep.text,
          name: dep.text,
          isLeaf: dep.leaf,
          scopedSlots: {
            title: 'title',
          },
        }
      })
    },
    downloadTemplate(field) {
      this.$set(this.downloadLoading, field.name, true)
      download(field.template.url, field.template.name + '.xls').finally(() => {
        this.$delete(this.downloadLoading, field.name)
      })
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.warp {
  // 由于直接使用的a-col配合sd-form-item做的表单布局，label与内容区域需要显示在一行，特此处理
  :global(.ant-form-item .ant-form-item-label) {
    float: left;
    width: 25%;
  }
  :global(.ant-form-item .ant-form-item-control-wrapper) {
    float: left;
    width: 75%;
  }
  .no-label {
    :global(.ant-form-item .ant-form-item-control-wrapper) {
      float: left;
      width: 100%;
    }
  }

  :global(.ant-form-item) {
    margin-bottom: auto;
  }
}
.act-table {
  width: 100%;

  .column-title {
    width: 30%;
  }
  td {
    padding: 5px 0 5px 5px;
    border: 1px solid;
  }
}
</style>
