<template>
  <a-modal
    v-model="visible"
    :width="800"
    title="代码导出"
    destroy-on-close
    @ok="() => exportCode()"
  >
    <sd-form ref="app" :init-values="values">
      <template v-slot="{ model }">
        <sd-form-item name="moduleName" />
        <sd-form-item name="basePkg">
          <a-input v-model="model.basePkg" @change="() => toLowerCase(model, 'basePkg')" />
        </sd-form-item>
        <sd-form-item name="modulePkg">
          <a-input v-model="model.modulePkg" @change="() => toLowerCase(model, 'modulePkg')" />
        </sd-form-item>
      </template>
    </sd-form>
    <a-tabs v-model="activeKey">
      <a-tab-pane v-for="data in datas" :key="data.head.id" :tab="data.head.tableTxt" force-render>
        <sd-form :ref="data.head.id" :init-values="formData">
          <template v-slot="{ model }">
            <sd-form-item name="tableSqlName">
              <a-input
                v-model="model.tableSqlName"
                @change="() => toUpperCase(model, 'tableSqlName')"
              />
            </sd-form-item>
            <sd-form-item name="className">
              <a-input
                v-model="model.className"
                @change="() => firstUpperCase(model, 'className')"
              />
            </sd-form-item>
            <sd-form-item name="businessPkg">
              <a-input
                v-model="model.businessPkg"
                @change="() => toLowerCase(model, 'businessPkg')"
              />
            </sd-form-item>
          </template>
        </sd-form>
      </a-tab-pane>
    </a-tabs>
  </a-modal>
</template>

<script>
import axios from '@/common/services/axios-instance'
import { Message } from 'ant-design-vue'
import download from '@/common/services/download'
import codeExport from '../form-designer/code-export'
import components from './_import-components/sd-export-import'
export default {
  name: 'SdExport',
  metaInfo: {},
  components,
  data() {
    return {
      activeKey: undefined,
      visible: false,
      datas: [],
      values: [
        {
          name: 'moduleName',
          caption: '项目名称',
          dataType: 'string',
        },
        {
          name: 'basePkg',
          caption: '生成包路径',
          dataType: 'string',
          required: true,
          attrFD: { description: '必须小写字母,且点分割，如com.hd.xcoa.project' },
          attr: {
            regex: /^[a-z]+(\.{1}[a-z]+)+$/,
            regexMessage: '不符合规范',
          },
        },
        {
          name: 'modulePkg',
          caption: '生成模块名称',
          dataType: 'string',
          required: true,
          attrFD: { description: '必须全小写字母，如modulexx' },
          attr: {
            regex: /^[a-z]+$/,
            regexMessage: '不符合规范',
          },
        },
      ],
      formData: [
        {
          name: 'tableSqlName',
          caption: '表名称',
          dataType: 'string',
          required: true,
          attrFD: { description: '必须大写且下划线分割，如XM_XX_TABLE' },
          attr: {
            regex: /^[A-Z]+(_{1}[A-Z|0-9]+)+$/,
            regexMessage: '不符合规范',
          },
        },
        {
          name: 'className',
          caption: '实体类名称',
          dataType: 'string',
          required: true,
          attrFD: { description: '必须全字母,且驼峰格式，如CommercialCar' },
          attr: {
            regex: /^[A-Z]{1}([a-z]*[A-Z]*)*$/,
            regexMessage: '不符合规范',
          },
        },
        {
          name: 'businessPkg',
          caption: '生成业务名',
          dataType: 'string',
          required: true,
          attrFD: { description: '必须全小写字母，如bizxx' },
          attr: {
            regex: /^[a-z]+$/,
            regexMessage: '不符合规范',
          },
        },
      ],
    }
  },
  methods: {
    show(appName, ids) {
      this.values[0].value = appName
      return Promise.all(
        ids.map((id) => {
          return axios.get(`api/framework/v1/onlineform/getById/${id}/true`)
        })
      )
        .then((res) => {
          const badForms = res.filter((item) => item.data.fields.length === 0)
          if (badForms.length) {
            Message.warn(
              '请先完善表单' +
                badForms.map((item) => item.data.head.tableTxt).join(',') +
                '再导出代码'
            )
            // eslint-disable-next-line prefer-promise-reject-errors
            return Promise.reject('请先完善表单')
          }
          return res.map((item) => item.data)
        })
        .then((datas) => {
          this.activeKey = datas[0].head.id
          this.datas = datas
          this.visible = true
        })
    },
    exportCode() {
      this.$refs.app.validateFields().then(() => {
        Promise.all(
          this.datas.map((data) => {
            return this.$refs[data.head.id][0].validateFields().catch(() => {
              this.activeKey = data.head.id
              // eslint-disable-next-line prefer-promise-reject-errors
              return Promise.reject('校验未通过')
            })
          })
        )
          .then(() => {
            const tableSqlName = this.datas.map(
              (data) => this.$refs[data.head.id][0].getFieldsValue().tableSqlName
            )
            const className = this.datas.map(
              (data) => this.$refs[data.head.id][0].getFieldsValue().className
            )
            const businessPkg = this.datas.map(
              (data) => this.$refs[data.head.id][0].getFieldsValue().businessPkg
            )
            if (tableSqlName.length !== [...new Set(tableSqlName)].length) {
              Message.warn('模块表名不能重复，请检查')
              return Promise.reject(new Error())
            }
            if (className.length !== [...new Set(className)].length) {
              Message.warn('实体类名称不能重复，请检查')
              return Promise.reject(new Error())
            }
            if (businessPkg.length !== [...new Set(businessPkg)].length) {
              Message.warn('生成业务名不能重复，请检查')
              return Promise.reject(new Error())
            }
          })
          .then(() => {
            this.datas.forEach((data) => {
              const formData = this.$refs[data.head.id][0].getFieldsValue()
              // 生成vue的表单名用
              data.head.tableName = formData.tableSqlName.replace(/_/g, '-').toLowerCase()
              // 拼pageId用
              data.head.businessPkg = formData.businessPkg
              // 拼pageId用，第一个字符要小写
              data.head.className = formData.className.replace(/( |^)[A-Z]/g, (L) =>
                L.toLowerCase()
              )
              // 拼pageId用和生产zip包名用
              data.head.modulePkg = this.$refs.app.getFieldValue('modulePkg')
            })
            codeExport(this.datas)
            // 后台代码
            download(
              {
                url: 'api/framework/v1/onlinecode/download',
                method: 'post',
                data: {
                  moduleName: this.$refs.app.getFieldValue('moduleName'),
                  basePkg: this.$refs.app.getFieldValue('basePkg'),
                  modulePkg: this.$refs.app.getFieldValue('modulePkg'),
                  codeAuthor: '',
                  multiDb: false,
                  forms: this.datas.map((data, index) => {
                    const formData = this.$refs[data.head.id][0].getFieldsValue()
                    return {
                      headId: data.head.id,
                      formRemarks: data.head.formDesc,
                      tableSqlName: formData.tableSqlName,
                      businessPkg: data.head.businessPkg,
                      className: formData.className,
                    }
                  }),
                },
              },
              this.datas[0].head.modulePkg + '后端代码.zip',
              true
            )
          })
      })
    },
    toLowerCase(model, field) {
      model[field] = model[field].toLowerCase()
    },
    toUpperCase(model, field) {
      model[field] = model[field].toUpperCase()
    },
    firstUpperCase(model, field) {
      const [...letters] = model[field]
      letters[0] = letters[0].toUpperCase()
      model[field] = letters.join('')
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
</style>
