<template>
  <div style="height: 100%">
    <DesignForm ref="designFormRef" v-bind="$attrs" />
    <FormPreviewDrawer @register="registerDrawer" />
  </div>
</template>
<script lang="ts" setup>
  import { DesignForm, noHaveTableAndField, remoteComponents } from '/@/components/Designer';
  import FormPreviewDrawer from './components/FormPreviewDrawer.vue';
  import { inject, ref, Ref, watch } from 'vue';
  import { useDrawer } from '/@/components/Drawer';
  import { GeneratorConfig } from '/@/model/generator/generatorConfig';
  import { TableFieldConfig } from '/@/model/generator/tableStructureConfig';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { ComponentOptionModel, FormJson } from '/@/model/generator/codeGenerator';
  import { unionWith, cloneDeep } from 'lodash-es';
  import {
    noHaveField,
    shortTextComponents,
    longTextComponents,
    integerComponents,
    decimalsComponents,
    dateTimeComponents,
    timeComponents,
  } from '/@/components/Designer';
  import { useI18n } from '/@/hooks/web/useI18n';

  const { t } = useI18n();
  const generatorConfig = inject<GeneratorConfig>('generatorConfig');
  const designType = inject<string>('designType');
  const isCustomForm = inject<boolean>('isCustomForm', false);
  const widgetForm = inject<any>('widgetForm');
  const { notification } = useMessage();
  const current = inject<Ref<number>>('current') as Ref<number>;
  const designFormRef = ref();
  const rangeComponents = ['time-range', 'date-range'];

  watch(
    () => current.value,
    () => {
      if (isCustomForm && designType == 'template') return;
      designFormRef.value.setWidgetFormSelect(widgetForm.value);
    },
  );
  //注册抽屉 获取外部操作抽屉得方法
  const [registerDrawer] = useDrawer();

  const setStructureConfig = () => {
    //新增时的配置信息
    const addStructureConfig = cloneDeep(generatorConfig!.tableStructureConfigs || []);
    generatorConfig!.tableStructureConfigs = [];
    let tableFieldConfigs = [] as TableFieldConfig[];

    getTableStructure(generatorConfig?.formJson.list, tableFieldConfigs);
    if (generatorConfig?.formJson.hiddenComponent?.length) {
      generatorConfig?.formJson.hiddenComponent.map((item) => {
        if (
          !generatorConfig?.tableStructureConfigs?.length ||
          !generatorConfig?.tableStructureConfigs[0]?.isMain
        ) {
          generatorConfig?.tableStructureConfigs?.unshift({
            tableName: item.bindTable,
            tableComment: '',
            isMain: true,
            tableFieldConfigs: [],
          });
        }
        if (generatorConfig?.tableStructureConfigs?.length) {
          generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.push({
            key: item.key,
            fieldName: item.bindField.substr(0, 30),
            fieldLength: 500,
            fieldType: 0,
            fieldComment: t('隐藏组件'),
          });
        }
      });
    }
    let isDataAuth = isCustomForm
      ? generatorConfig?.isDataAuth
      : generatorConfig?.outputConfig?.isDataAuth;

    //自定义表单界面优先、简易模板开启了数据权限则新增rule_user_id字段
    if (isDataAuth) {
      const hasRuleUserField =
        generatorConfig?.tableStructureConfigs?.length &&
        generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.find(
          (x) => x.key === 'rule_user_id',
        );
      if (hasRuleUserField) return;
      generatorConfig?.tableStructureConfigs?.length &&
        generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.push({
          key: 'rule_user_id',
          fieldName: 'rule_user_id',
          fieldLength: 500,
          fieldType: 7,
          fieldComment: t('数据权限所属人ID'),
        });
    } else {
      if (generatorConfig?.tableStructureConfigs?.length) {
        generatorConfig.tableStructureConfigs[0].tableFieldConfigs =
          generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.filter(
            (x) => x.key !== 'rule_user_id',
          );
      }
    }
    let isCommonFields = isCustomForm
      ? generatorConfig?.isCommonFields
      : generatorConfig?.outputConfig?.isCommonFields;

    const fields = [
      'create_user_id',
      'create_user_name',
      'create_date',
      'modify_user_id',
      'modify_date',
      'delete_mark',
      'enabled_mark',
    ];
    if (isCommonFields) {
      const commonFields = [
        {
          key: 'create_user_id',
          fieldName: 'create_user_id',
          fieldType: 6,
          fieldLength: null,
          fieldComment: t('创建人'),
        },
        {
          key: 'create_user_name',
          fieldName: 'create_user_name',
          fieldType: 0,
          fieldLength: 500,
          fieldComment: t('创建人名称'),
        },
        {
          key: 'create_date',
          fieldName: 'create_date',
          fieldType: 5,
          fieldLength: null,
          fieldComment: t('创建时间'),
        },
        {
          key: 'modify_user_id',
          fieldName: 'modify_user_id',
          fieldType: 6,
          fieldLength: null,
          fieldComment: t('修改人'),
        },
        {
          key: 'modify_date',
          fieldName: 'modify_date',
          fieldType: 5,
          fieldLength: null,
          fieldComment: t('修改时间'),
        },
        {
          key: 'delete_mark',
          fieldName: 'delete_mark',
          fieldType: 2,
          fieldLength: null,
          fieldComment: t('删除字段'),
        },
        {
          key: 'enabled_mark',
          fieldName: 'enabled_mark',
          fieldType: 2,
          fieldLength: null,
          fieldComment: t('标记字段'),
        },
      ];
      const hasCommonField =
        generatorConfig?.tableStructureConfigs?.length &&
        generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.find((x) =>
          fields.includes(x.key!),
        );
      if (hasCommonField) return;
      generatorConfig?.tableStructureConfigs?.length &&
        generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.push(...commonFields);
    } else {
      if (generatorConfig?.tableStructureConfigs?.length) {
        generatorConfig.tableStructureConfigs[0].tableFieldConfigs =
          generatorConfig?.tableStructureConfigs[0].tableFieldConfigs.filter(
            (x) => !fields.includes(x.key!),
          );
      }
    }
    if (designType === 'code' && addStructureConfig.length) {
      //编辑回显
      addStructureConfig.forEach((addConfig) => {
        generatorConfig!.tableStructureConfigs!.forEach((config) => {
          if (addConfig.tableName === config.tableName) {
            config.tableComment = addConfig.tableComment;
            addConfig.tableFieldConfigs?.forEach((subAddConfig) => {
              config.tableFieldConfigs?.forEach((subConfig) => {
                if (subAddConfig.fieldName === subConfig.fieldName) {
                  subConfig.fieldType = subAddConfig.fieldType;
                  subConfig.fieldLength = subAddConfig.fieldLength;
                  subConfig.fieldComment = subAddConfig.fieldComment;
                }
              });
            });
          }
        });
      });
    }
  };

  const getTableStructure = (list, tableFieldConfigs, table?, tableKey?) => {
    list?.map((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          getTableStructure(child.list, tableFieldConfigs);
        }
      } else if (item.type === 'table-layout') {
        for (const child of item.layout!) {
          for (const el of child.list) {
            getTableStructure(el.children, tableFieldConfigs);
          }
        }
      } else if (item.type === 'form' || item.type === 'one-for-one' || item.type === 'sun-form') {
        let subTableFieldConfigs = [] as TableFieldConfig[];
        generatorConfig?.tableStructureConfigs?.push({
          key: item.key,
          tableName: item.bindTable,
          tableComment: '',
          isMain: false,
          tableFieldConfigs: subTableFieldConfigs,
          parentTable: item.type === 'sun-form' ? table : undefined,
          parentKey: item.type === 'sun-form' ? tableKey : undefined,
        });
        if (item.type === 'form' || item.type === 'sun-form') {
          item.children?.map((subItem) => {
            if (!noHaveField.includes(subItem.type) || rangeComponents.includes(subItem.type)) {
              setTableFieldConfigs(subItem, subTableFieldConfigs);
            }
            if (subItem.type === 'sun-form') {
              getTableStructure([subItem], subTableFieldConfigs, item.bindTable, item.key);
            }
          });
        } else {
          getSimpleTableStructure(item.children, subTableFieldConfigs);
        }
      } else if (
        (!noHaveField.includes(item.type) && item.type !== 'input') ||
        rangeComponents.includes(item.type) ||
        (item.type == 'input' && !item.options.isSave)
      ) {
        if (
          !generatorConfig?.tableStructureConfigs?.length ||
          !generatorConfig?.tableStructureConfigs[0].isMain
        ) {
          generatorConfig?.tableStructureConfigs?.unshift({
            tableName: item.bindTable,
            tableComment: '',
            isMain: true,
            tableFieldConfigs,
          });
        }

        if (generatorConfig?.tableStructureConfigs?.length) {
          setTableFieldConfigs(item, generatorConfig?.tableStructureConfigs[0].tableFieldConfigs);
        }
      }
    });
  };
  const getSimpleTableStructure = (list, tableFieldConfigs) => {
    list?.map((item) => {
      if (['tab', 'grid', 'card'].includes(item.type)) {
        for (const child of item.layout!) {
          getSimpleTableStructure(child.list, tableFieldConfigs);
        }
      } else if (item.type === 'table-layout') {
        for (const child of item.layout!) {
          for (const el of child.list) {
            getSimpleTableStructure(el.children, tableFieldConfigs);
          }
        }
      } else if (!noHaveField.includes(item.type) || rangeComponents.includes(item.type)) {
        setTableFieldConfigs(item, tableFieldConfigs);
      }
    });
  };
  const setTableFieldConfigs = (item, tableFieldConfigs) => {
    if (rangeComponents.includes(item.type)) {
      tableFieldConfigs.push({
        key: item.key,
        fieldStartName: item.bindStartTime,
        fieldName: item.bindStartTime.substr(0, 30),
        fieldLength: !getFieldType(item.type) ? 500 : null,
        fieldType: getFieldType(item.type),
        fieldComment: t(`{types}开始时间`, { types: item.label }),
      });
      tableFieldConfigs.push({
        key: item.key,
        fieldEndName: item.bindEndTime,
        fieldName: item.bindEndTime.substr(0, 30),
        fieldLength: !getFieldType(item.type) ? 500 : null,
        fieldType: getFieldType(item.type),
        fieldComment: t(`{types}结束时间`, { types: item.label }),
      });
    } else if (item.type === 'info' && item.options.infoType === 2) {
      //信息体组件 选择当前时间情况
      tableFieldConfigs.push({
        key: item.key,
        fieldName: item.bindField.substr(0, 30),
        fieldLength: null,
        fieldType: 5,
        fieldComment: item.label!,
      });
    } else {
      if (item.options.isSave && item.type == 'input') return;
      tableFieldConfigs.push({
        key: item.key,
        fieldName: item.bindField.substr(0, 30),
        fieldLength: !getFieldType(item.type) ? 500 : null,
        fieldType: getFieldType(item.type),
        fieldComment: item.label!,
      });
    }
  };

  const getFieldType = (type) => {
    switch (type) {
      case shortTextComponents.find((x) => x === type):
        return 0;
      case longTextComponents.find((x) => x === type):
        return 1;
      case integerComponents.find((x) => x === type):
        return 2;
      case decimalsComponents.find((x) => x === type):
        return 3;
      case dateTimeComponents.find((x) => x === type):
        return 5;
      case timeComponents.find((x) => x === type):
        return 8;
      default:
        return 0;
    }
  };

  //验证当前步骤的数据
  const validateStep = async (): Promise<boolean> => {
    if (designType !== 'data') {
      setStructureConfig();
    }
    const formJson = designFormRef.value.getJson() as FormJson;

    //formJson 是否为空 或者 一个组件都没有
    if (!formJson || formJson.list.length === 0) {
      notification.error({
        message: t('提示'),
        description: t('表单设计不能为空！'),
      }); //提示消息
      return false;
    }

    const { tableConfigs } = generatorConfig as GeneratorConfig;
    const mainTableName = tableConfigs?.find((x) => x.isMain)?.tableName;

    //先判断所有非子表组件  是否包含主表字段  如果一个主表字段都没有 提示
    const getMainComponent = (list?) => {
      if (!list) return [];
      let mainComponents = [] as Recordable[];
      for (const item of list) {
        if (['tab', 'grid', 'card'].includes(item.type)) {
          for (const child of item.layout!) {
            mainComponents = unionWith(mainComponents, getMainComponent(child.list));
          }
        } else if (item.type === 'table-layout') {
          for (const child of item.layout!) {
            for (const el of child.list) {
              mainComponents = unionWith(mainComponents, getMainComponent(el.children));
            }
          }
        } else {
          if (item.bindTable === mainTableName) {
            mainComponents.push(item);
          }
        }
      }
      return mainComponents;
    };

    //获取子表中的字段
    const getSubField = (list, subTableFieldList = {}) => {
      for (const item of list) {
        if (['tab', 'grid', 'card'].includes(item.type)) {
          for (const child of item.layout!) {
            getSubField(child.list, subTableFieldList);
          }
        }
        if (item.type === 'form' || item.type === 'one-for-one') {
          if (!item.children.length) return;
          if (!subTableFieldList[item.bindTable]) subTableFieldList[item.bindTable] = [];
          item.children.forEach((x) => {
            if (['tab', 'grid', 'card'].includes(x.type)) {
              for (const child of x.layout!) {
                getSubField(child.list, subTableFieldList);
              }
            } else if (rangeComponents.includes(x.type)) {
              subTableFieldList[item.bindTable].push(x.bindStartTime);
              subTableFieldList[item.bindTable].push(x.bindEndTime);
            } else {
              if (x.bindField) subTableFieldList[item.bindTable].push(x.bindField);
            }
          });
        } else if (item.isSingleFormChild) {
          if (rangeComponents.includes(item.type)) {
            subTableFieldList[item.bindTable].push(item.bindStartTime);
            subTableFieldList[item.bindTable].push(item.bindEndTime);
          } else {
            if (item.bindField) subTableFieldList[item.bindTable].push(item.bindField);
          }
        }
      }
      return subTableFieldList;
    };

    //判断子表的同一表中 是否有重复字段
    const subTableHasSameField = () => {
      const subTableFieldList = getSubField(formJson.list);
      const hasSameFieldList: boolean[] = [];
      if (!Object.keys(subTableFieldList!).length) return false;
      for (let key in subTableFieldList) {
        const res = subTableFieldList[key].length === new Set(subTableFieldList[key]).size;
        hasSameFieldList.push(res);
      }
      return hasSameFieldList.some((x) => !x);
    };

    //主表中的所有字段
    const mainTableFieldList: string[] = [];
    getMainComponent(formJson.list).forEach((item) => {
      if (rangeComponents.includes(item.type)) {
        mainTableFieldList.push(item.bindStartTime);
        mainTableFieldList.push(item.bindEndTime);
      } else {
        mainTableFieldList.push(item.bindField);
      }
    });

    //界面优先、简易模板 判断子表里面是否有组件
    const hasSubFormComponents = generatorConfig?.tableStructureConfigs
      ?.filter((x) => !x.isMain)
      .every((x) => !!x.tableFieldConfigs.length);

    if (!getMainComponent(formJson.list).length && designType === 'data') {
      notification.error({
        message: t('提示'),
        description: t('表单设计未绑定一个主表字段，最少得包含一个主表字段！'),
      }); //提示消息
      return false;
    }
    if (
      generatorConfig?.tableStructureConfigs &&
      !generatorConfig?.tableStructureConfigs[0]?.isMain &&
      designType !== 'data'
    ) {
      notification.error({
        message: t('提示'),
        description: t('表单设计未添加生成主表字段的组件，请先添加后再进行下一步。'),
      }); //提示消息
      return false;
    }
    //判断是否多表  但是没有子表单组件
    if (
      (designType === 'data' &&
        tableConfigs!.length > 1 &&
        sumSubFormComponent(formJson.list) !==
          tableConfigs!.filter((x) => !x.isMain && x.isSubForm).length) ||
      (designType !== 'data' && !hasSubFormComponents)
    ) {
      notification.error({
        message: t('提示'),
        description: t('有子表未绑定组件！'),
      }); //提示消息
      return false;
    }
    if (designType === 'data' && mainTableFieldList.length > new Set(mainTableFieldList).size) {
      notification.error({
        message: t('提示'),
        description: t('主表中有组件绑定相同字段！'),
      }); //提示消息
      return false;
    }
    if (designType === 'data' && subTableHasSameField()) {
      notification.error({
        message: t('提示'),
        description: t('子表中有组件绑定相同字段！'),
      }); //提示消息
      return false;
    }
    //判断隐藏组件是否填写完整
    if (formJson.hiddenComponent?.length) {
      const isCompelete = formJson.hiddenComponent.every((com) => {
        return Object.values(com).every((val) => val !== '');
      });
      if (!isCompelete) {
        notification.error({
          message: t('提示'),
          description: t('隐藏组件需填写完整'),
        }); //提示消息
        return false;
      }
    }
    //判断表单按钮是否填写完整
    if (formJson.buttonList?.length) {
      const isCompelete = formJson.buttonList.every((com) => {
        return Object.values({ code: com.code, name: com.name }).every((val) => val !== '');
      });
      if (!isCompelete) {
        notification.error({
          message: t('提示'),
          description: t('表单自定义按钮需填写完整'),
        }); //提示消息
        return false;
      }
    }
    //一个个组件遍历
    const message = validateComponent(formJson.list);

    if (message) {
      notification.error({
        message: t('提示'),
        description: message,
      }); //提示消息
      return false;
    }

    return true;
  };

  const validateComponent = (list: ComponentOptionModel[]) => {
    for (const component of list) {
      //布局组件需要递归子集
      if (['card', 'tab', 'form', 'grid', 'one-for-one'].includes(component.type)) {
        //如果是子表单 默认取 children中的组件  其他的 都是取layout中的组件
        if (component.type === 'form' || component.type === 'one-for-one') {
          if (!component.bindTable) {
            return t(`{name}(子表单)未绑定表`, { name: component.label });
          }

          if (!component.children || component.children.length === 0) {
            return t(`{name}(子表单)的子组件不能为空`, { name: component.label });
          }
          //如果子组件有错误  直接返回顶级
          const errorMsg = validateComponent(component.children);
          if (errorMsg) {
            return errorMsg;
          }
        } else {
          if (!component.layout || component.layout.length === 0) {
            return t(`{name}组件布局不能为空`, { name: component.label });
          }

          for (const item of component.layout) {
            const errorMsg = validateComponent(item.list);
            if (errorMsg) {
              return errorMsg;
            }
          }
        }
      }
      if (component.type === 'table-layout') {
        for (const item of component.layout!) {
          for (const list of item.list) {
            if (list.children && list.children.length > 0) {
              const errorMsg = validateComponent(list.children);
              if (errorMsg) {
                return errorMsg;
              }
            }
          }
        }
      }
      if (
        component.type === 'signature' &&
        !component.options!.defaultValue.length &&
        !component.options!.associateComponents!.length
      ) {
        return `${component.label}未选择默认值或关联组件`;
      }

      if (
        noHaveTableAndField.includes(component.type) ||
        component.type === 'form' ||
        component.type === 'one-for-one'
      ) {
        //如果是不需要绑定字段的 默认跳过验证
        continue;
      }

      //如果是时间区间组件 必须要绑定2个字段  一个开始时间  一个结束时间
      if (component.type === 'range') {
        if (!component.bindStartTime) {
          return t(`{name}未绑定开始时间字段`, { name: component.label });
        }
        if (!component.bindEndTime) {
          return t(`{name}未绑定结束时间字段`, { name: component.label });
        }
      }

      //级联组件 必须选择级联配置
      if (component.type === 'cascader' && !component.options!.apiConfig.apiId) {
        return t(`{name}未选择级联配置`, { name: component.label });
      }

      //如果是远程组件并且是 数据源  或者 数据字典 方式
      if (
        remoteComponents.includes(component.type) &&
        component.options!.datasourceType !== 'staticData'
      ) {
        if (component.options!.datasourceType === 'dic') {
          if (!component.options!.itemId) {
            return t(`{name}未选择数据字典`, { name: component.label });
          }
          if (!component.options!.dicOptions?.length && component.type === 'associate-popup') {
            return t(`{name}未进行联想配置`, { name: component.label });
          }

          if (!component.options!.dicOptions?.length && component.type === 'multiple-popup') {
            return t(`{name}未进行显示配置`, { name: component.label });
          }
        }
        if (component.options!.datasourceType === 'api') {
          if (!component.options!.apiConfig.apiId) {
            return t(`{name}未选择API`, { name: component.label });
          }
          if (!component.options!.apiConfig.outputParams && component.type === 'associate-popup') {
            return t(`{name}未进行联想配置`, { name: component.label });
          }

          if (!component.options!.apiConfig.outputParams && component.type === 'multiple-popup') {
            return t(`{name}未进行显示配置`, { name: component.label });
          }
        }

        if (component.options!.datasourceType === 'datasource') {
          if (!component.options!.sourceId) {
            return t(`{name}未选择数据源`, { name: component.label });
          }
          if (!component.options!.labelField) {
            return t(`{name}未选择数据源显示字段`, { name: component.label });
          }
          if (!component.options!.valueField) {
            return t(`{name}未选择数据源保存字段`, { name: component.label });
          }
        }
      }
      // TODO  这里继续写各组件自己特有的一些验证
      if (
        (component.type == 'input' && !component.options!.isSave && !component.bindTable) ||
        (component.type !== 'input' && !component.bindTable)
      ) {
        return t(`{name}未绑定表`, { name: component.label });
      }

      if (
        !component.bindField &&
        !component.type.includes('range') &&
        component.type !== 'sun-form' &&
        component.type !== 'modal' &&
        component.type !== 'drawer'
      ) {
        return t(`{name}未绑定字段`, { name: component.label });
      }

      if (
        component.type.includes('range') &&
        (!component.bindStartTime || !component.bindEndTime)
      ) {
        return t(`{name}未绑定开始字段或结束字段`, { name: component.label });
      }
      if (component.type === 'auto-code' && !component.options!.autoCodeRule) {
        return t(`{name}未选择编码规则`, { name: component.label });
      }
    }
    return '';
  };

  //遍历所有组件 是否有子表单
  const sumSubFormComponent = (list: ComponentOptionModel[]): number => {
    let totalSubForm = 0;
    for (const component of list) {
      if (
        (component.type === 'form' || component.type === 'one-for-one') &&
        !!component.bindTable &&
        component.children?.length
      ) {
        totalSubForm++;
      }

      //布局组件需要递归子集
      if (['card', 'tab', 'grid'].includes(component.type)) {
        //如果是子表单 默认取 children中的组件  其他的 都是取layout中的组件
        if (!component.layout || component.layout.length === 0) {
          continue;
        }
        for (const item of component.layout) {
          totalSubForm += sumSubFormComponent(item.list);
        }
      }
      if (component.type === 'table-layout') {
        for (const item of component.layout!) {
          for (const list of item.list!) {
            if (list.children && list.children.length > 0) {
              totalSubForm += sumSubFormComponent(list.children);
            }
          }
        }
      }
    }
    return totalSubForm;
  };
  defineExpose({ validateStep, setStructureConfig, designFormRef });
</script>
