<template>
  <div class="step1-box">
    <div class="step1">
      <div class="step1-form">
        <BasicForm @register="register" />
      </div>
      <template v-if="designType === 'data'">
        <Divider />
        <div class="database-title">
          <span>
            添加数据库表（请先选择数据库-第一个选择的为主库，次表为附表的附表，仅能用作关联附表使用）
          </span>
          <a-button type="primary" @click="add">
            <PlusOutlined />
            {{ t('新增') }}
          </a-button>
        </div>
        <div>
          <a-table
            rowKey="tableName"
            :columns="columns"
            :data-source="generatorConfig?.tableConfigs"
            :pagination="false"
          >
            <template #bodyCell="{ column, record, index }">
              <template v-if="column.key === 'order'">
                <span>
                  {{ index + 1 }}
                </span>
              </template>
              <template v-if="column.key === 'isMain'">
                <span>
                  <a-tag v-if="record.isMain" color="blue"> 主表 </a-tag>
                  <a-select
                    v-else
                    v-model:value="record.isSubForm"
                    class="w-4/5"
                    @change="handleTableForm(record)"
                  >
                    <a-select-option :value="true">附表</a-select-option>
                    <a-select-option :value="false">次表</a-select-option>
                  </a-select>
                </span>
              </template>
              <template v-else-if="column.key === 'relationField'">
                <template v-if="record.isSubForm">
                  <Select
                    style="width: 200px"
                    v-model:value="record[column.key]"
                    :placeholder="t('请选择附表关联主表字段')"
                  >
                    <SelectOption
                      v-for="(name, idx) in selectOptions[record.tableName]"
                      :key="idx"
                      :value="name"
                    >
                      {{ name }}
                    </SelectOption>
                  </Select>
                </template>
              </template>
              <template v-else-if="column.key === 'relationTableField'">
                <template v-if="record.isSubForm">
                  <Select
                    style="width: 200px"
                    v-model:value="record[column.key]"
                    :placeholder="t('请选择主表字段')"
                  >
                    <SelectOption
                      v-for="(name, idx) in selectOptions[mainTable]"
                      :key="idx"
                      :value="name"
                    >
                      {{ name }}
                    </SelectOption>
                  </Select>
                </template>
              </template>
              <template v-else-if="column.key === 'action'">
                <span @click="remove(index)" class="delete-span">删除</span>
              </template>
            </template>
            <template #expandedRowRender="{ record }" v-if="!isUpdate">
              <a-table
                style="margin: 0"
                v-if="record.isMain"
                :columns="fieldColumns"
                :data-source="innerData[record.tableName]"
                :pagination="false"
              >
                <template #bodyCell="{ column, record }">
                  <template v-if="column.dataIndex === 'name'">
                    <div>{{ record.name }}</div>
                  </template>
                  <template v-else-if="column.dataIndex === 'length'">
                    <div>{{ record.length }}</div>
                  </template>
                  <template v-else-if="column.dataIndex === 'columnComment'">
                    <a-input
                      v-model:value.number="record.columnComment"
                      :placeholder="t('请填写备注')"
                    />
                  </template>
                  <template v-else-if="column.dataIndex === 'type'">
                    <div>{{ handleTypeChange(record.type) }}</div>
                  </template>
                </template>
              </a-table>
            </template>
          </a-table>
        </div>
        <SelectDatabase @register="registerModal" @success="handleSelectSuccess" />
      </template>
    </div>
  </div>
</template>
<script lang="ts" setup>
  import { computed, inject, Ref, ref, toRaw, watch } from 'vue';
  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
  import { getDatabaselinkMultiTableColumns } from '/@/api/system/databaselink';
  import { getAuthList } from '/@/api/system/authorize';
  import { Divider } from 'ant-design-vue';
  import { PlusOutlined } from '@ant-design/icons-vue';
  import { useModal } from '/@/components/Modal';
  import { SelectDatabase } from '/@/components/CreateCodeStep';
  import { Select } from 'ant-design-vue';
  import { cloneDeep, debounce, uniqBy } from 'lodash-es';
  import { TableConfig } from '/@/model/generator/tableConfig';
  import { CustomFormConfig, GeneratorConfig } from '/@/model/generator/generatorConfig';
  import { useMessage } from '/@/hooks/web/useMessage';
  import {
    TableInfo,
    FieldInfo,
    upperFieldDb,
    fieldTypeList,
    fieldTypeCompMap,
    ColumnType,
  } from '/@/components/Designer';
  import { JavaTypeConvertTsType } from '/@/utils/helper/designHelper';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { FormJson } from '/@/model/generator/codeGenerator';
  import { buildUUID } from '/@/utils/uuid';
  import * as antd from '/@/components/Designer/src/types';

  const props = defineProps({
    isUpdate: Boolean,
  });
  const { t } = useI18n();
  const SelectOption = Select.Option;

  const { notification } = useMessage();
  const curDataBase = ref();

  const dataAuthPlaceholder = computed(() => {
    return generatorConfig!.isDataAuth ? t('请选择已有通用数据权限') : t('请先启用数据权限');
  });
  const dataAuthHelpMessage = `
      1.启用数据权限会判断主表是否包含RuleUserlD字段如果存在，则不进行表结构修改，如果不存在，则会对主表进行字段添加。
      2.RuleUserlD主要用来控制每一条记录的权限所属人新增时，默认将当前登录认作为权限所属人。
      3.在表单设计中会添加“批量设置权限所属人”功能启用后，拥有该按钮权限的人员可以设置每一条记录的权限所属人。
        `;

  const commonHelpMessage = `
        1.审计字段包括创建人ID、创建人名称、创建时间、最后修改人、最后修改时间、逻辑删除、标记字段。
        2.如果开启“审计字段”开关，则系统会自动实现相关操作，就是在新增时操作创建人、创建时间，编辑时操作最后修改人、最后修改时间，删除时改为逻辑删除，标记字段则标记字段是否有效。
        `;
  const innerData = ref({});
  const formSchemaData: FormSchema[] = [
    {
      field: 'name',
      label: t('表单名称'),
      required: true,
      component: 'Input',
      colProps: {
        span: 12,
      },
      componentProps: {
        placeholder: t('请输入表单名称'),
        onChange: debounce((val: ChangeEvent) => {
          customFormConfig!.name = val.target.value;
        }, 200),
      },
    },
    {
      field: 'category',
      label: t('表单分类'),
      component: 'DicSelect',
      required: true,
      componentProps: {
        placeholder: t('请选择表单分类'),
        itemId: '1419276800524424444',
        isShowAdd: false,
        onChange: debounce((id) => {
          customFormConfig!.category = id;
        }, 200),
      },
      colProps: { span: 12 },
    },
    {
      field: 'remark',
      label: t('功能描述'),
      component: 'Input',
      colProps: { span: 12 },
      componentProps: {
        placeholder: t('请输入功能描述'),
        onChange: debounce((val: ChangeEvent) => {
          customFormConfig!.remark = val.target.value;
        }, 200),
      },
    },
    {
      field: 'databaseId',
      label: t('数据库'),
      component: 'DbSelect',
      required: true,
      colProps: { span: 12 },
      componentProps: {
        placeholder: t('请选择数据库'),
        onChange: debounce((val, option) => {
          generatorConfig!.databaseId = val;
          if (option) isFieldUpper.value = upperFieldDb.includes(option.dbType);
          mainTableName.value = isFieldUpper.value
            ? mainTableName.value.toUpperCase()
            : mainTableName.value;

          if (curDataBase.value && curDataBase.value !== val) {
            generatorConfig!.tableConfigs = [];
          }

          curDataBase.value = val;
        }, 200),
      },
    },
    {
      field: 'isDataAuth',
      label: t('数据权限'),
      component: 'Switch',
      required: false,
      colProps: { span: 12 },
      helpMessage: dataAuthHelpMessage,
      helpComponentProps: { maxWidth: '400px' },
      componentProps: {
        checkedValue: true,
        unCheckedValue: false,
        onChange: (val) => {
          if (!val) {
            setFieldsValue({ dataAuthList: [] });
            generatorConfig!.dataAuthList = [];
          }
          generatorConfig!.isDataAuth = val;
        },
      },
    },
    {
      field: 'dataAuthList',
      label: t('权限选择'),
      component: 'ApiSelect',
      required: false,
      colProps: { span: 12 },
      componentProps: {
        mode: 'multiple',
        placeholder: dataAuthPlaceholder,
        api: getAuthList,
        labelField: 'name',
        valueField: 'id',
        getPopupContainer: () => document.body,
        onChange: (val) => {
          generatorConfig!.dataAuthList = val;
        },
      },
      dynamicDisabled: ({ values }) => {
        return !values.isDataAuth;
      },
    },
  ];

  const formSchemaNoTable: FormSchema[] = [
    {
      field: 'name',
      label: t('表单名称'),
      required: true,
      component: 'Input',
      colProps: {
        span: 12,
      },
      componentProps: {
        placeholder: t('请输入表单名称'),
        onChange: debounce((val: ChangeEvent) => {
          customFormConfig!.name = val.target.value;
        }, 200),
      },
    },
    {
      field: 'category',
      label: t('表单分类'),
      component: 'DicSelect',
      required: true,
      componentProps: {
        placeholder: t('请选择表单分类'),
        itemId: '1419276800524424444',
        isShowAdd: false,
        onChange: debounce((id) => {
          customFormConfig!.category = id;
        }, 200),
      },
      colProps: { span: 12 },
    },
    {
      field: 'remark',
      label: t('功能描述'),
      component: 'Input',
      colProps: { span: 12 },
      componentProps: {
        placeholder: t('请输入功能描述'),
        onChange: debounce((val: ChangeEvent) => {
          customFormConfig!.remark = val.target.value;
        }, 200),
      },
    },
  ];

  const formSchema: FormSchema[] = [
    {
      field: 'name',
      label: t('表单名称'),
      required: true,
      component: 'Input',
      colProps: {
        span: 12,
      },
      componentProps: {
        placeholder: t('请输入表单名称'),
        onChange: debounce((val: ChangeEvent) => {
          customFormConfig!.name = val.target.value;
        }, 200),
      },
    },
    {
      field: 'category',
      label: t('表单分类'),
      component: 'DicSelect',
      required: true,
      componentProps: {
        placeholder: t('请选择表单分类'),
        itemId: '1419276800524424444',
        isShowAdd: false,
        onChange: debounce((id) => {
          customFormConfig!.category = id;
        }, 200),
      },
      colProps: { span: 12 },
    },
    {
      field: 'remark',
      label: t('功能描述'),
      component: 'Input',
      colProps: { span: 12 },
      componentProps: {
        placeholder: t('请输入功能描述'),
        onChange: debounce((val: ChangeEvent) => {
          customFormConfig!.remark = val.target.value;
        }, 200),
      },
    },
    {
      field: 'isCommonFields',
      label: t('审计字段'),
      component: 'Switch',
      required: false,
      colProps: { span: 12 },
      helpMessage: commonHelpMessage,
      helpComponentProps: { maxWidth: '400px' },
      componentProps: {
        checkedValue: true,
        unCheckedValue: false,
        onChange: (val) => {
          generatorConfig!.isCommonFields = val;
        },
      },
    },
    {
      field: 'isDataAuth',
      label: t('数据权限'),
      component: 'Switch',
      required: false,
      colProps: { span: 12 },
      helpMessage: dataAuthHelpMessage,
      helpComponentProps: { maxWidth: '400px' },
      componentProps: {
        checkedValue: true,
        unCheckedValue: false,
        onChange: (val) => {
          if (!val) {
            setFieldsValue({ dataAuthList: [] });
            generatorConfig!.dataAuthList = [];
          }
          generatorConfig!.isDataAuth = val;
        },
      },
    },
    {
      field: 'dataAuthList',
      label: t('权限选择'),
      component: 'ApiSelect',
      required: false,
      colProps: { span: 12 },
      componentProps: {
        mode: 'multiple',
        placeholder: dataAuthPlaceholder,
        api: getAuthList,
        labelField: 'name',
        valueField: 'id',
        getPopupContainer: () => document.body,
        onChange: (val) => {
          generatorConfig!.dataAuthList = val;
        },
      },
      dynamicDisabled: ({ values }) => {
        return !values.isDataAuth;
      },
    },
    {
      field: 'toDataFirst',
      label: '转为数据优先',
      component: 'Switch',
      required: false,
      colProps: { span: 12 },
      helpMessage:
        '打开开关，在设置完成后，“界面优先模板”及“简易模板”将转化为“数据优先模板”在代码模板中存在。',
      helpComponentProps: { maxWidth: '400px' },
      componentProps: {
        checkedValue: true,
        unCheckedValue: false,
        onChange: (val) => {
          generatorConfig!.toDataFirst = val;
        },
      },
    },
  ];

  const columns = [
    {
      title: '#',
      dataIndex: 'order',
      key: 'order',
      width: 80,
    },
    {
      title: t('类别'),
      dataIndex: 'isMain',
      key: 'isMain',
      width: 120,
      align: 'center',
    },
    {
      title: t('表名'),
      dataIndex: 'tableName',
      key: 'tableName',
      align: 'center',
    },
    {
      title: t('关联字段'),
      dataIndex: 'relationField',
      key: 'relationField',
      align: 'center',
    },
    {
      title: t('关联表字段'),
      key: 'relationTableField',
      dataIndex: 'relationTableField',
      align: 'center',
    },
    {
      title: t('操作'),
      key: 'action',
      align: 'center',
    },
  ];
  const fieldColumns = [
    {
      title: t('字段名'),
      dataIndex: 'name',
      align: 'center',
    },
    {
      title: t('字段长度'),
      dataIndex: 'length',
      align: 'center',
    },
    {
      title: t('数据格式'),
      dataIndex: 'type',
      align: 'center',
    },
    {
      title: t('备注'),
      dataIndex: 'columnComment',
      align: 'center',
    },
  ];
  const selectOptions = ref({});
  const selectTableName = computed(() =>
    generatorConfig!.tableConfigs!.map((item) => item.tableName),
  );
  const handleTypeChange = (value) => {
    let obj = fieldTypeList.find((o) => {
      return o.value == value;
    });
    if (obj) return obj.label;
    return '';
  };
  const mainTable = computed(
    () => generatorConfig!.tableConfigs!.find((item) => item.isMain)!.tableName,
  );

  const generatorConfig = inject<GeneratorConfig>('generatorConfig');
  const customFormConfig = inject<CustomFormConfig>('customFormConfig');
  const tableInfo = inject<Ref<TableInfo[]>>('tableInfo');
  const designType = inject<string>('designType');
  const isFieldUpper = inject<Ref<boolean>>('isFieldUpper', ref(false));
  let mainTableName = inject<Ref<string>>('mainTableName', ref(''));
  const widgetForm = inject('widgetForm') as any;
  watch(
    () => generatorConfig?.databaseId,
    (val, oldVal) => {
      const { tableConfigs } = generatorConfig!;
      if (
        designType === 'data' &&
        val &&
        val !== oldVal &&
        tableConfigs &&
        tableConfigs.length > 0
      ) {
        getDatabaselinkColumns(val);
      }
    },
  );

  const [registerModal, { openModal }] = useModal();

  const schemas = computed(() => {
    if (designType === 'data') {
      return formSchemaData;
    } else if (designType === 'notable') {
      return formSchemaNoTable;
    } else {
      return formSchema;
    }
  });

  const [register, { validate, getFieldsValue, setFieldsValue }] = useForm({
    schemas,
    showActionButtonGroup: false,
    layout: 'vertical',
    rowProps: { gutter: 32 },
  });

  const add = async () => {
    try {
      const values = await validate();
      openModal(true, {
        databaseId: values.databaseId,
        selectTableName: selectTableName.value,
      });
    } catch (error) {}
  };

  const handleSelectSuccess = (selectRows: TableConfig[]) => {
    if (generatorConfig?.tableConfigs && generatorConfig?.tableConfigs.length === 0) {
      generatorConfig!.tableConfigs = [...toRaw(selectRows)];
    } else {
      generatorConfig!.tableConfigs = uniqBy(
        generatorConfig!.tableConfigs!.concat([...selectRows]),
        'tableName',
      );
    }
    const formData = getFieldsValue();
    getDatabaselinkColumns(formData.databaseId);
  };

  const remove = (index) => {
    // TODO 这里删除 可能会引起 表单设计步骤所有的设计 出错。3个解决方案
    //1 删除后提示用户 表单设计全部清空！
    //2 删除之后根据所删除的表名  去表单设计Json匹配 所绑定的组件 全部将绑定表置空！
    //3 表单设计后 不允许删除表配置！

    //如果删除的数据是主表 并且还有其他表  默认顺序 找下一张表 将其设为主表
    if (generatorConfig!.tableConfigs![index].isMain && generatorConfig!.tableConfigs!.length > 1) {
      const nextObj = generatorConfig!.tableConfigs![index + 1];
      nextObj.isMain = true;
      nextObj.relationField = '';
      nextObj.relationTableField = '';

      const nextTable = tableInfo!.value![index + 1];
      nextTable.isMain = true;

      generatorConfig!.tableConfigs!.splice(index, 1);
      tableInfo?.value.splice(index, 1);
    } else {
      generatorConfig!.tableConfigs!.splice(index, 1);
      tableInfo?.value.splice(index, 1);
    }
  };
  const getDatabaselinkColumns = (databaseId) => {
    getDatabaselinkMultiTableColumns({
      id: databaseId,
      tableNames: selectTableName.value.join(','),
    }).then((result) => {
      for (const key in result) {
        const columnInfo = result[key];
        //如果已经写入过的表格 不再添加
        if (!tableInfo?.value.find((x) => x.name === key)) {
          const fields = columnInfo.map((field) => {
            const filedInfo: FieldInfo = {
              name: field.column,
              length: field.dataLength,
              type: JavaTypeConvertTsType(field.dataType),
              isPk: field.primaryKey,
              isNullable: field.nullable,
            };
            return filedInfo;
          });
          const info = generatorConfig!.tableConfigs!.find((x) => x.tableName === key);

          tableInfo?.value.push({
            name: key,
            isMain: info?.isMain as boolean,
            isSubForm: info?.isSubForm as boolean,
            fields: fields,
          });
          const thisTableConfig = generatorConfig!.tableConfigs!.find((x) => x.tableName === key);

          const col = columnInfo.find((x) => x.primaryKey);
          thisTableConfig!.pkField = col.column;
          thisTableConfig!.pkType = col.dataType;

          innerData.value[key] = fields;
        }

        selectOptions.value[key] = columnInfo.map((x) => x.column);
      }
    });
  };

  const handleTableForm = (info) => {
    tableInfo?.value.forEach((item) => {
      if (item.name === info.tableName) item.isSubForm = info.isSubForm;
    });
    if (info.isSubForm === false) {
      info.relationField = '';
      info.relationTableField = '';
    }
  };
  const allComponents = [
    ...antd.basicComponents,
    ...antd.advanceComponents,
    ...antd.buttonComponents,
    ...antd.layoutComponents,
    ...antd.workFlowComponents,
    ...antd.infoComponents,
    ...antd.financeComponents,
  ];
  //验证当前步骤的数据
  const validateStep = async (): Promise<boolean> => {
    try {
      await validate();
      if (designType !== 'data') {
        return true;
      }
      const { tableConfigs } = generatorConfig as GeneratorConfig;

      //判断tableconfig 是否为空 或者 一条数据都没有
      if (!tableConfigs || tableConfigs!.length === 0) {
        notification.error({
          message: t('提示'),
          description: t('数据表配置不能为空！'),
        }); //提示消息
        return false;
      }

      for (const config of tableConfigs!) {
        //如果是主表 可以不需要关联字段等
        if (config.isMain || !config.isSubForm) {
          if (!config.tableName) {
            notification.error({
              message: t('提示'),
              description: t('主表表名未能配置成功！'),
            }); //提示消息
            return false;
          }
        } else {
          //子表需要验证关联字段 已经关联表 是否选择好
          if (!config.tableName) {
            notification.error({
              message: t('提示'),
              description: t('子表表名未能配置成功！'),
            }); //提示消息
            return false;
          }

          if (!config.relationField) {
            notification.error({
              message: t('提示'),
              description: t(`{name} 表 关联字段未选中`, { name: config.tableName }),
            }); //提示消息
            return false;
          }

          if (!config.relationTableField) {
            notification.error({
              message: t('提示'),
              description: t(`{name} 表 关联表字段未选中`, { name: config.tableName }),
            }); //提示消息
            return false;
          }
        }
      }
      if (!props.isUpdate) {
        let formJson: FormJson = {
          list: [],
          config: {
            formType: 'modal',
            size: 'default',
            layout: 'vertical',
            labelAlign: 'right',
            labelCol: {
              span: 3,
              offset: 0,
            },
            formWidth: 900,
          },
          hiddenComponent: [],
        };
        for (const config of tableConfigs!) {
          //如果是主表
          if (config.isMain) {
            let fields = innerData.value[config.tableName];
            const list: any = [];
            fields.forEach((f) => {
              if (
                !(
                  (f.type == ColumnType.KEY && f.length < 19) ||
                  (f.type == ColumnType.LONGTEXT && f.length < 200)
                )
              ) {
                let obj: any = allComponents.find((a) => {
                  return a.type == (f.isPk ? 'input' : fieldTypeCompMap[f.type]);
                });
                if (obj) {
                  let form = cloneDeep(obj);
                  if (f.columnComment) form.label = f.columnComment;
                  form.options.placeholder = t(
                    ([4, 5, 6, 8].includes(f.type) ? '请选择' : '请输入') + form.label,
                  );
                  form.key = buildUUID();
                  form.model = fieldTypeCompMap[f.type] + '_' + form.key;
                  form.bindField = f.name;
                  form.bindTable = config.tableName;
                  list.push(form);
                }
              }
            });
            formJson.list = list;
            generatorConfig.formJson = formJson;
            widgetForm.value = formJson;
          }
        }
      }
    } catch (error) {
      return false;
    }
    return true;
  };

  defineExpose({ validateStep, setFieldsValue });
</script>
