<template>
  <Modal
    centered
    :title="title"
    :width="modalWidth"
    :visible="visible"
    :confirmLoading="confirmLoading"
    @ok="handleSubmit"
    @cancel="handleCancel"
    cancelText="取消"
    okText="生成代码"
    wrapClassName="ant-modal-cust-warp"
  >
    <Form ref="formRef" :model="formData" :rules="rules">
      <Row :gutter="24">
        <Col :span="24">
          <FormItem
            label="生成目录"
            :labelCol="!single ? labelCol2 : labelCol"
            :wrapperCol="!single ? wrapperCol2 : wrapperCol"
            :rules="[
              {
                required: true,
                message: '请选择代码生成目录!',
                trigger: 'blur'
              }
            ]"
          >
            <a-input-search
              @change="storeProjectPath"
              placeholder="请选择代码生成目录"
              @search="onSelectDir"
              v-model:value="formData.projectPath"
            >
              <template #enterButton>
                <c-button preIcon="ant-design:folder-open-outlined">浏览</c-button>
              </template>
            </a-input-search>
          </FormItem>
        </Col>

        <Col :span="!single ? 12 : 24">
          <FormItem label="页面风格" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <Select v-model:value="formData.jspMode">
              <SelectOption v-for="(item, index) in jspModeList" :value="item.code" :key="index">{{
                item.note
              }}</SelectOption>
            </Select>
          </FormItem>
        </Col>

        <Col :span="!single ? 12 : 24">
          <FormItem label="功能说明" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <a-input placeholder="请输入功能说明" v-model:value="formData.ftlDescription" allowClear />
          </FormItem>
        </Col>

        <Col :span="!single ? 12 : 24" v-show="false">
          <FormItem label="数据模型" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <Select disabled>
              <SelectOption value="1">单表</SelectOption>
              <SelectOption value="2">一对多</SelectOption>
            </Select>
          </FormItem>
        </Col>

        <Col :span="!single ? 12 : 24">
          <FormItem name="tableName" label="表名" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <a-input disabled placeholder="请输入表名" v-model:value="formData.tableName" />
          </FormItem>
        </Col>

        <Col :span="!single ? 12 : 24">
          <FormItem label="实体类名" :labelCol="labelCol" :wrapperCol="wrapperCol" name="entityName">
            <a-input placeholder="请输入实体类名(首字母大写)" v-model:value="formData.entityName" allowClear />
          </FormItem>
        </Col>

        <Col :span="!single ? 12 : 24">
          <FormItem label="包名(小写)" :labelCol="labelCol" :wrapperCol="wrapperCol" name="entityPackage">
            <a-input placeholder="请输入包名" v-model:value="formData.entityPackage" allowClear />
          </FormItem>
        </Col>

        <Col :span="!single ? 12 : 24">
          <FormItem label="代码分层样式" :labelCol="labelCol" :wrapperCol="wrapperCol">
            <Select disabled v-model:value="formData.packageStyle">
              <SelectOption value="service">业务分层</SelectOption>
              <SelectOption value="project">代码分层</SelectOption>
            </Select>
          </FormItem>
        </Col>

        <Col :span="24">
          <FormItem
            label="页面代码"
            :labelCol="!single ? labelCol2 : labelCol"
            :wrapperCol="!single ? wrapperCol2 : wrapperCol"
          >
            <RadioGroup name="radioGroup" v-model:value="formData.vueStyle">
              <Radio value="vue3Native">Vue3原生(a-form)</Radio>
              <Radio value="vue3">Vue3(BasicForm)</Radio>
              <Radio value="vue2">Vue2</Radio>
            </RadioGroup>
          </FormItem>
        </Col>

        <Col :span="24" v-show="false">
          <FormItem label="需要生成的代码" :labelCol="!single ? labelCol2 : labelCol" :wrapperCol="wrapperCol">
            <Checkbox :trigger-change="true" :options="genCodeTypes" />
          </FormItem>
        </Col>
      </Row>

      <Card title="子表信息" v-if="subInfoList && subInfoList.length > 0" :class="{ 'online-gen-subinfo': true }">
        <JVxeTable
          ref="tableRef3"
          keepSource
          rowNumber
          :maxHeight="580"
          :columns="subInfoColumn"
          :dataSource="subInfoList"
        />
      </Card>
    </Form>

    <file-select-modal ref="fsm" @callback="updateFileDir" />
    <!-- 生成结果提示页面 -->
    <Modal title="代码生成 成功了！" :visible="generateLogVisible" :width="1200" @cancel="generateLogVisible = false">
      <template #footer>
        <!--        <c-button key="back" @click="handleGenerateOk">下载到本地</c-button>-->
        <c-button key="cancel" @click="generateLogVisible = false">取消</c-button>
        <c-button key="submit" type="primary" @click="generateLogVisible = false">确认关闭</c-button>
      </template>
      <p style="line-height: 10px" v-for="(item, index) in generateLogList" :key="index">{{ item }}</p>
    </Modal>
  </Modal>
</template>

<script lang="ts" name="CodeGenerator" setup>
  import { ref } from 'vue';
  import { onlyMessage } from '@jdlinker/utils';
  import { getAction, postAction, downFile } from '../../../../../api/manage';
  import FileSelectModal from './FileSelectModal.vue';
  import { JCheckbox } from '@jdlinker/ui';
  import { underLine2CamelCase } from '@jdlinker/utils';
  import type { Rule } from 'ant-design-vue/es/form';
  import { subInfoColumn } from '../cgform.data';
  import { Modal, Form, Row, Col, Card, FormItem, Select, SelectOption, RadioGroup, Radio, Checkbox } from 'ant-design-vue';

  const rules: Record<string, Rule[]> = {
    entityName: [{ required: true, message: '请输入实体类名!', trigger: 'change' }],
    entityPackage: [{ required: true, message: '请输入包名!', trigger: 'change' }]
  };
  const project_path = 'linker_onl_project_path';
  const title = ref('代码生成');
  const modalWidth = ref(800);
  const visible = ref(false);
  const fsm = ref();
  const confirmLoading = ref(false);
  const formRef = ref();
  const code = ref('');
  const subInfoList = ref([]);
  const single = ref(false);
  const formData = ref<any>({
    projectPath: '',
    packageStyle: 'service',
    vueStyle: 'vue3'
  });
  const jspModeList = ref<any>([]);
  //生成结果提示页面，所用参数
  const generateLogList = ref<any>([]);
  const generateLogVisible = ref(false);
  const generateTableName = ref('');
  const metaModel: any = ref({
    projectPath: '',
    packageStyle: 'service',
    vueStyle: 'vue3',
    jspMode: '',
    jformType: '1',
    tableName: '',
    ftlDescription: '',
    entityName: '',
    codeTypes: 'controller,service,dao,mapper,entity,vue'
  });
  const labelCol = {
    xs: { span: 24 },
    sm: { span: 6 }
  };
  const labelCol2 = {
    xs: { span: 24 },
    sm: { span: 3 }
  };
  const wrapperCol = {
    xs: { span: 24 },
    sm: { span: 16 }
  };
  const wrapperCol2 = {
    xs: { span: 24 },
    sm: { span: 20 }
  };
  const genCodeTypes = [
    {
      label: 'controller',
      value: 'controller'
    },
    {
      label: 'service',
      value: 'service'
    },
    {
      label: 'dao',
      value: 'dao'
    },
    {
      label: 'mapper.xml',
      value: 'mapper'
    },
    {
      label: 'entity',
      value: 'entity'
    },
    {
      label: 'vue',
      value: 'vue'
    }
  ];
  const url = {
    tableInfo: '/online/cgform/head/tableInfo',
    codeGenerate: '/online/cgform/api/codeGenerate',
    downGenerateCode: '/online/cgform/api/downGenerateCode'
  };
  const handleSubmit = async () => {
    confirmLoading.value = true;
    formRef.value
      ?.validate()
      .then(() => {
        let data = Object.assign({}, formData.value, {
          code: code.value,
          subInfoList: subInfoList.value
        });
        postAction(url.codeGenerate, data).then((res) => {
          if (res.success) {
            handleCancel();
            //生成结果提示代码
            generateLogList.value = res.result;
            generateLogVisible.value = true;
            generateTableName.value = data.tableName;
          } else {
            onlyMessage(res.message, 'warning');
          }
          confirmLoading.value = false;
          formRef.value.resetFields();
        });
      })
      .catch((error) => {
        formRef.value.resetFields();
        console.log('error', error);
      });
  };
  const handleCancel = () => {
    visible.value = false;
  };
  /**
   * 下载生成代码
   */
  const handleGenerateOk = () => {
    generateLogVisible.value = false;
    var params = {
      fileList: encodeURI(generateLogList.value)
    };
    downFile(url.downGenerateCode, params).then((data) => {
      if (!data || data.size == 0) {
        onlyMessage('导出代码失败！', 'warning');
        return;
      }
      let fileName = '导到生成代码_' + generateTableName.value + '_' + new Date().getTime() + '.zip';
      if (typeof window.navigator.msSaveBlob !== 'undefined') {
        window.navigator.msSaveBlob(new Blob([data], { type: 'application/zip' }), fileName);
      } else {
        let url = window.URL.createObjectURL(new Blob([data], { type: 'application/zip' }));
        let link = document.createElement('a');
        link.style.display = 'none';
        link.href = url;
        link.setAttribute('download', fileName);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link); //下载完成移除元素
        window.URL.revokeObjectURL(url); //释放掉blob对象
      }
    });
  };
  const show = (codeVal) => {
    confirmLoading.value = false;
    visible.value = true;
    //当前主表ID
    code.value = codeVal;
    subInfoList.value = [];
    formData.value = Object.assign({}, metaModel.value);
    modalWidth.value = 800;
    getStoreProjectPath();
    getAction(url.tableInfo, { code: codeVal }).then((res) => {
      if (res.success) {
        let mainInfo = res.result.main;
        console.log('主数据：' + mainInfo);
        jspModeList.value = [...res.result.jspModeList];
        if (mainInfo.isTree == 'Y') {
          formData.value.jspMode = 'tree';
        } else {
          formData.value.jspMode = jspModeList.value[0].code;
        }
        single.value = mainInfo.tableType == 1;
        title.value = '代码生成【' + mainInfo.tableName + '】';
        if (!formData.value.projectPath) {
          formData.value.projectPath = res.result.projectPath;
          localStorage.setItem(project_path, res.result.projectPath);
        }
        formData.value.jformType = mainInfo.tableType + '';
        formData.value.tableName = mainInfo.tableName;
        formData.value.ftlDescription = mainInfo.tableTxt;
        let tempentyame = underLine2CamelCase(mainInfo.tableName);
        formData.value.entityName = tempentyame.substring(0, 1).toUpperCase() + tempentyame.substring(1);
        if (res.result.sub && res.result.sub.length > 0) {
          subInfoList.value = res.result.sub.map((item) => {
            return {
              id: item.id,
              tableName: item.tableName,
              entityName: getCamelCase(item.tableName),
              tableTxt: item.tableTxt
            };
          });
          jspModeList.value = jspModeList.value.filter((item) => item.code != 'many');
          formData.value.jspMode = jspModeList.value[0].code;
          modalWidth.value = 1200;
        }
      } else {
        onlyMessage('表信息加载失败', 'warning');
      }
    });
  };
  const onSelectDir = () => {
    fsm.value.show();
  };
  const updateFileDir = (url) => {
    formData.value.projectPath = url;
  };
  const getCamelCase = (val) => {
    let tempentyame = underLine2CamelCase(val);
    return tempentyame.substring(0, 1).toUpperCase() + tempentyame.substring(1);
  };
  const storeProjectPath = (e) => {
    if (e.target.value) localStorage.setItem(project_path, e.target.value);
  };
  const getStoreProjectPath = () => {
    let path = localStorage.getItem(project_path);
    if (path) {
      metaModel.value.projectPath = path;
    }
  };
  defineExpose({ show });
</script>

<style scoped>
  .online-gen-subinfo .ant-card-body {
    padding: 18px 5px 0 5px;
  }

  .online-gen-subinfo .ant-card-head {
    min-height: 32px;
  }
  .online-gen-subinfo .ant-card-head-title {
    padding: 8px 0;
  }
  .ant-select-disabled .ant-select-selection {
    background-color: #fff;
    color: #00000094;
  }
  :deep(.ant-card-head-title) {
    padding: 10px 0;
  }
</style>
