<template>
  <div :class="$style.fullHeight">
    <a-row :gutter="24" :class="$style.fullHeight">
      <a-col :md="5" :sm="24" :class="$style.fullHeight">
        <a-card :class="$style.fullHeight">
          <sd-sysparams-tree ref="tree" @selected="selected" @hierarchyChange="hierarchyChange" />
        </a-card>
      </a-col>
      <a-col :class="$style.fullHeight" :md="19" :sm="24">
        <a-card :class="$style.fullHeight">
          <sd-data-table
            v-if="selectedKey"
            ref="table"
            data-url="api/framework/v1/dict-manager/getvalues"
            :columns="columns"
            :actions="actions"
            :search-fields="['name', 'valueId']"
            :filter-expressions="expressions"
            :row-key="(record) => record.id + record.keyId"
            show-selection
            @rowClick="rowClick"
          >
            <span slot="id" slot-scope="text">{{ text.slice(1) }}</span>
          </sd-data-table>
        </a-card>
      </a-col>
    </a-row>
    <div>
      <a-modal
        :visible="visible"
        title="参数维护"
        :width="800"
        destroy-on-close
        @cancel="visible = false"
        @ok="handleOk"
      >
        <sd-sysparams-form ref="form" />
      </a-modal>
      <a-modal
        :visible="importVisible"
        title="导入参数"
        :width="800"
        destroy-on-close
        :confirm-loading="confirmImportLoading"
        @cancel="importCancel"
        @ok="checkParameterExist"
      >
        <sd-form ref="importForm" :init-values="importFormData">
          <template v-slot="{ model }">
            <sd-form-item name="deptId">
              <template>
                <sd-tree-picker
                  ref="tree"
                  v-model="model.deptId"
                  :load-tree-data="loadTreeData"
                  single
                  option-value="id"
                  option-label="text"
                />
              </template>
            </sd-form-item>
            <sd-form-item name="attachment">
              <a-upload-dragger
                name="file"
                :multiple="false"
                accept=".gz"
                :custom-request="(file) => customRequest(file)"
                :file-list="fileList"
                @change="handleChange"
              >
                <p class="ant-upload-drag-icon">
                  <a-icon type="inbox" />
                </p>
                <p class="ant-upload-text">
                  点击或将文件拖拽到这里上传
                </p>
              </a-upload-dragger>
            </sd-form-item>
          </template>
        </sd-form>
      </a-modal>
      <a-modal
        :visible="checkListVisible"
        title="冲突字典项/字典值"
        :width="800"
        destroy-on-close
        @cancel="checkListVisible = false"
        @ok="importParameterOk"
      >
        <div>
          <span :class="$style.radioText">导入字典项/字典值策略</span>
          <a-radio-group v-model="conflictStrategy">
            <a-radio value="0">
              跳过导入字典项/字典值
            </a-radio>
            <a-radio value="1">
              覆盖导入字典项/字典值
            </a-radio>
          </a-radio-group>
        </div>
        <div :class="$style.conflictList">
          <a-list bordered :data-source="conflictKeyList">
            <a-list-item slot="renderItem" slot-scope="item">
              {{ item }}
            </a-list-item>
            <div slot="header" :class="$style.listHeader">
              已存在字典项
            </div>
          </a-list>
        </div>
        <div :class="$style.conflictList">
          <a-list bordered :data-source="conflictValueList">
            <a-list-item slot="renderItem" slot-scope="item">
              {{ item }}
            </a-list-item>
            <div slot="header" :class="$style.listHeader">
              已存在字典值
            </div>
          </a-list>
        </div>
      </a-modal>
      <a-modal
        :visible="exportVisible"
        title="导出参数"
        :width="800"
        destroy-on-close
        @cancel="exportVisible = false"
        @ok="exportParameterOk"
      >
        <a-tree
          v-model="checkedKeys"
          :load-data="onLoadData"
          :tree-data="treeData"
          checkable
          :default-expanded-keys="['CXXX']"
        />
      </a-modal>
    </div>
  </div>
</template>

<script>
import { Modal, Message } from 'ant-design-vue'
import axios from '@/common/services/axios-instance'
import TableActionTypes from '@/common/services/table-action-types'
import download from '@/common/services/download'
import SysparamsService from './sysparams-service'
import components from './_import-components/sd-sysparams-maintain-import'
const formatTree = (arr) => {
  arr.forEach((item) => {
    item.title = item.title || item.text
    item.isLeaf = item.leaf
    item.key = item.id
    if (item.children) formatTree(item.children)
  })
}

export default {
  name: 'SdSysparamsMaintain',
  metaInfo: {
    title: '参数维护',
  },
  components,
  props: {
    module: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      columns: [
        {
          dataIndex: 'keyId',
          defaultSortOrder: 'asc',
          sdHidden: true,
        },
        {
          dataIndex: 'id',
          title: 'ID',
          scopedSlots: { customRender: 'id' },
        },
        {
          dataIndex: 'index',
          title: '序号',
          defaultSortOrder: 'asc',
        },
        {
          dataIndex: 'name',
          title: '名称',
          sdClickable: !this.module,
        },
      ],
      selectedKey: '',
      visible: false,
      importVisible: false,
      exportVisible: false,
      checkListVisible: false,
      fileList: [],
      groupId: '',
      loadingMsg: null,
      treeData: [
        {
          keyId: 'CXXX',
          title: '参数管理',
          key: 'CXXX',
          id: 'CXXX',
          isLeaf: false,
        },
      ],
      checkedKeys: [],
      defaultExpandedKey: ['CXXX'],
      conflictStrategy: '0',
      conflictKeyList: [],
      conflictValueList: [],
      confirmImportLoading: false,
      msgKey: 'updatable',
      importFormData: [
        {
          name: 'deptId',
          dataType: 'String',
          caption: '目标字典项',
          readonly: false,
          required: true,
        },
        {
          name: 'attachment',
          dataType: 'attachment',
          caption: '数据文件',
          readonly: false,
          required: true,
        },
      ],
      actions: this.module
        ? []
        : [
            {
              label: '新建',
              id: 'new',
              permission: 'dictValuePerms-create',
              type: TableActionTypes.primary,
              callback: () => {
                this.visible = true
                this.$nextTick(() => {
                  this.$refs.form.setFieldsValue({
                    keyId: this.selectedNodes,
                    props: { create: 1 },
                  })
                })
              },
            },
            {
              label: '删除',
              id: 'delete',
              permission: 'dictValuePerms-delete',
              type: TableActionTypes.batch,
              callback: (keys) => {
                Modal.confirm({
                  title: '确认删除所有选中的字典值吗？',
                  okText: '删除',
                  okType: 'danger',
                  onOk: () => {
                    const params = {
                      parentId: this.selectedKey.slice(1),
                      ids: this.$refs.table
                        .getSelectedRows()
                        .map((item) => item.privateCode || item.id),
                    }
                    SysparamsService.delSysclassify(params)
                      .then(() => {
                        this.$refs.table.refresh()
                        this.$refs.tree.refresh()
                      })
                      .catch((e) => {
                        Message.error({ content: '删除失败' })
                      })
                  },
                })
              },
            },
            {
              label: '导入',
              id: 'import',
              permission: null,
              type: TableActionTypes.common,
              callback: this.importFile,
            },
            {
              label: '导出',
              id: 'export',
              permission: null,
              type: TableActionTypes.common,
              callback: this.exportFile,
            },
          ],
    }
  },
  computed: {
    expressions() {
      const params = [
        {
          dataType: 'long',
          name: 'belongOrgId',
          op: 'eq',
          longValue: this.groupId,
        },
      ]
      return params.concat(
        this.selectedKey === 'CXXX'
          ? []
          : [
              {
                dataType: 'str',
                name: 'keyId',
                op: 'eq',
                stringValue: this.selectedKey,
              },
            ]
      )
    },
  },
  methods: {
    exportFile() {
      this.exportVisible = true
      this.checkedKeys = []
    },
    handleChange(info) {
      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('attachment', fileList)
      this.fileList = fileList
    },
    loadTreeData() {
      return SysparamsService.getTreeData().then((res) => {
        if (res.data.length) {
          res.data.forEach((item) => {
            item.isLeaf = item.leaf
          })
          return res.data
        }
      })
    },
    selected(key, selectedNodes) {
      this.selectedNodes = [selectedNodes]
      this.selectedKey = key
    },
    hierarchyChange(hierarchy) {
      this.groupId = hierarchy[0]?.id
    },
    rowClick(record) {
      this.visible = true
      this.$nextTick(() => {
        record.keyId = this.selectedNodes
        this.$refs.form.setFieldsValue(record)
      })
    },
    importFile() {
      this.importVisible = true
    },
    handleOk() {
      this.$refs.form.validateFields().then(() => {
        const params = { ...this.$refs.form.getFieldsValue() }
        params.keyId = params.keyId[0].id
        params.belongOrgId = this.groupId
        SysparamsService.saveValues(params).then(() => {
          this.visible = false
          this.$refs.table.refresh()
          this.$refs.tree.refresh()
        })
      })
    },
    customRequest(options) {
      if (options.file.size === 0) {
        Message.warn(`不能上传大小为0的文件`)
        return
      }
      const formData = new FormData()
      formData.append('file', options.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) {
            options.onSuccess(res.data, options)
          } else {
            Message.warn(`上传失败`)
          }
        })
        .catch((e) => {
          throw e
        })
    },
    onLoadData(treeNode) {
      const params = {
        listValue: true,
        isOpenAuth: true,
        groupId: this.groupId,
        keyId: treeNode?.dataRef.id || 'CXXX',
      }
      return SysparamsService.getExportParamsTree(params).then((res) => {
        if (res.data) {
          treeNode.dataRef.children = res.data
          formatTree(this.treeData)
          this.treeData = [...this.treeData]
        }
      })
    },
    importCancel() {
      this.importVisible = false
      this.confirmImportLoading = false
      this.fileList = []
    },
    checkParameterExist() {
      this.$refs.importForm.validateFields().then(() => {
        this.confirmImportLoading = true
        this.loadingMsg = Message.loading({
          key: this.msgKey,
          content: '处理中...',
          duration: 0,
        })
        const values = this.$refs.importForm.getFieldsValue()
        SysparamsService.checkParameterExist({
          groupId: this.groupId,
          tmpFileInfo: values.attachment[0].response,
          conflictStrategy: '0',
        })
          .then((res) => {
            if (res.status === 200) {
              const { keyList, valueList } = res.data
              if (keyList.length === 0 && valueList.length === 0) {
                this.importParameterOk()
                return
              }
              this.conflictKeyList = keyList
              this.conflictValueList = valueList
              this.checkListVisible = true
            } else {
              Message.error(res.data?.Message || '处理失败')
            }
          })
          .catch(() => {
            Message.error('处理失败')
          })
          .finally(() => {
            this.loadingMsg?.()
            this.confirmImportLoading = false
          })
      })
    },
    importParameterOk() {
      this.importVisible = false
      this.checkListVisible = false
      this.loadingMsg = Message.loading({
        key: this.msgKey,
        content: '导入中...',
        duration: 0,
      })
      const values = this.$refs.importForm.getFieldsValue()
      const params = {
        groupId: this.groupId,
        tmpFileInfo: values.attachment[0].response,
        conflictStrategy: this.conflictStrategy,
        deptId: values.deptId[0].id,
      }
      SysparamsService.importParameter(params)
        .then(() => {
          this.fileList = []
          Message.success('导入成功')
        })
        .catch(() => {
          Message.error('导入失败')
        })
        .finally(() => {
          this.loadingMsg?.()
        })
    },
    exportParameterOk() {
      this.exportVisible = false
      this.loadingMsg = Message.loading({
        key: this.msgKey,
        content: '处理中...',
        duration: 0,
      })
      SysparamsService.exportParameter(this.groupId, this.checkedKeys.join(','))
        .then((res) => {
          if (res.status === 200) {
            return download(
              `api/framework/v1/tmp-file/download/${res.data.id}`,
              `${res.data.name}`,
              true
            )
          } else {
            Message.error(res.data?.Message || '处理失败')
          }
        })
        .catch(() => Message.error('导出失败'))
        .finally(() => {
          this.loadingMsg?.()
        })
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.full-height {
  height: 100%;
  :global .ant-card-body {
    height: 100%;
    overflow: auto;
  }
}
.radio-text {
  margin-right: 12px;
}
/* stylelint-disable*/
.conflict-list {
  margin-top: 12px;
  .list-header {
    font-weight: 500;
    color: rgba(0, 0, 0, 0.85);
    &::after {
      display: inline-block;
      font-family: SimSun, sans-serif;
      font-size: 16px;
      line-height: 1;
      color: #f5222d;
      content: '*';
    }
  }
}
</style>
