<template>
  <a-spin :spinning="loading">
    <div class="form-container">
      <!-- 表单头部 -->
      <form-header
        @save="save"
        @upgradeAndSave="upgradeAndSave"
        @clearAll="clearAll"
        @back="back"
        @typeChange="typeChange"
        :formModelName="formModelName"
      ></form-header>
      <div class="form-view-container">
        <!-- 左侧选择组件 -->
        <form-left
          ref="formLeftRef"
          @addItem="addItem"
          :equipmentType="equipmentType"
          :setGlobalConfigState="setGlobalConfigState"
          @handleSetSelectItem="handleSetSelectItem"
          @componentNameListChange="componentNameListChange"
          @formTemplateClick="formTemplateClick"
        ></form-left>
        <!-- 表单内容 -->
        <form-component-view
          id="imageDom"
          :current-item="formConfig.currentItem"
          :data="formConfig"
          :isHidden="false"
          :isDesgin="true"
          @handleSetSelectItem="handleSetSelectItem"
        ></form-component-view>
        <!-- 右侧组件属性 -->
        <form-right :equipmentType="equipmentType" :componentNameList="componentNameList" :getBindFieldList="getBindFieldList"></form-right>
      </div>
    </div>
  </a-spin>
</template>

<script setup name="FormDesign">
import { defineAsyncComponent, ref, provide, onMounted, computed } from 'vue';
import { generateKey, formItemsForEach, isParamEmpty } from './utils/index';
import { cloneDeep } from 'lodash-es';
import { useRoute, useRouter } from 'vue-router';
import { FormDesignApi } from './api/FormDesignApi';
import { MetaUserDictApi } from './api/MetaUserDictApi';
import { ModelApi } from '../../mid/app/sheet/api/ModelApi';
import { message } from 'ant-design-vue/es';
import { useGeneratorStore } from '@/store/modules/generator';
import { Modal } from 'ant-design-vue';
import { getUUID } from '@/utils/common/util';

defineOptions({
  name: 'FormDesign'
});

const FormHeader = defineAsyncComponent(() => import('./components/form-header.vue'));
const FormLeft = defineAsyncComponent(() => import('./components/form-left.vue'));
const FormRight = defineAsyncComponent(() => import('./components/form-right.vue'));
const FormComponentView = defineAsyncComponent(() => import('./components/form-component-view.vue'));

// 路由
const route = useRoute();
const router = useRouter();

const generatorStore = useGeneratorStore();

// 当前选中应用数据
const buinessSelectAppData = computed(() => generatorStore.buinessSelectAppData ?? {});

// 全局的占比
const globalConfigState = ref({
  span: 12
});

// 默认表单配置
const defaultConfig = ref({
  // 表单配置
  formItems: [],
  config: {
    layout: 'vertical',
    labelLayout: 'flex',
    labelWidth: 100,
    labelCol: {},
    rowGutter: 16,
    wrapperCol: {},
    formWidth: null
  },
  currentItem: {
    componentCode: '',
    props: {}
  },
  activeKey: 1
});

// 表单配置
const formConfig = ref(cloneDeep(defaultConfig.value));

// pc端表单配置
const pcFormConfig = ref(cloneDeep(defaultConfig.value));

// 手机端端表单配置
const mobileFormConfig = ref(cloneDeep(defaultConfig.value));

// 字典类型列表
const dictTypeList = ref([]);
// 视图选择列表
const viewSelectList = ref([]);
// 选择子表列表
const selectSheetList = ref([]);
// 绑定字段列表
const bindFieldList = ref([]);

// 表单id
const formModelId = ref('');
// 表单名称
const formModelName = ref('');
// 当前的模型定义id  用于升级
const formDefinitionId = ref('');
// 当前设备类型
const equipmentType = ref('1');
// ref
const formLeftRef = ref(null);
// 组件默认名称列表
const componentNameList = ref([]);

const loading = ref(false);

onMounted(() => {
  if (!route.query.formModelId) return back();
  formModelId.value = route.query.formModelId;
  formDefinitionId.value = route.query.formDefinitionId;
  formModelName.value = route.query.formModelName;
  initData();
  getPcFormConfig();
  getMobileFormConfig();
});

const initData = async () => {
  dictTypeList.value = await MetaUserDictApi.getDictTypeList();
  viewSelectList.value = await FormDesignApi.getViewSelectList();
  if (buinessSelectAppData.value?.businessId) {
    selectSheetList.value = await ModelApi.list({ businessId: buinessSelectAppData.value.businessId, findSubFlag: true });
    getBindFieldList();
  }
};

const getBindFieldList = async () => {
  bindFieldList.value = await ModelApi.getTotalModelAndFieldList({ businessId: buinessSelectAppData.value.businessId });
};

// 获取pc表单配置
const getPcFormConfig = () => {
  loading.value = true;
  FormDesignApi.getFormConfig({ formDefinitionId: formDefinitionId.value, mobileFlag: false })
    .then(res => {
      if (res.formConfig && JSON.stringify(res.formConfig) != '{}') {
        pcFormConfig.value.config = res.formConfig;
      }
      pcFormConfig.value.currentItem = {};
      pcFormConfig.value.formItems = res.formItemList ?? [];
      if (equipmentType.value == '1') {
        formConfig.value = pcFormConfig.value;
      }
    })
    .finally(() => (loading.value = false));
};

// 获取移动端表单配置
const getMobileFormConfig = () => {
  loading.value = true;
  FormDesignApi.getFormConfig({ formDefinitionId: formDefinitionId.value, mobileFlag: true })
    .then(res => {
      if (res.formConfig && JSON.stringify(res.formConfig) != '{}') {
        mobileFormConfig.value.config = res.formConfig;
      }
      mobileFormConfig.value.currentItem = {};
      mobileFormConfig.value.formItems = res.formItemList ?? [];
      if (equipmentType.value == '2') {
        formConfig.value = mobileFormConfig.value;
      }
    })
    .finally(() => (loading.value = false));
};

// 返回设计页面
const back = () => {
  let backUrl = generatorStore.appBackUrl;
  let path = '/mid/app/detail';
  if (backUrl == '/mid/app/pandect') {
    path = '/mid/app/table';
  }
  router.push({
    path: path,
    query: {
      type: 'form'
    }
  });
};

// 默认名称列表
const componentNameListChange = arr => {
  componentNameList.value = arr;
};

// 表单模板点击
const formTemplateClick = item => {
  const { formConfig, mobileFormConfig: mobileConfig } = item;
  clearFormTemplateFieldCode(formConfig.formItemList);
  clearFormTemplateFieldCode(mobileConfig.formItemList);
  if (mobileFormConfig.value.formItems.length == 0 && pcFormConfig.value.formItems.length == 0) {
    setFormConfigData(formConfig, mobileConfig);
  } else {
    Modal.confirm({
      title: '提示',
      content: '您是否要清空并覆盖已有数据？',
      maskClosable: true,
      onOk: () => {
        setFormConfigData(formConfig, mobileConfig);
      }
    });
  }
};

// 设置表单配置
const setFormConfigData = (formConfig, mobileConfig) => {
  if (formConfig.formConfig && JSON.stringify(formConfig.formConfig) != '{}') {
    pcFormConfig.value.config = formConfig.formConfig;
  }
  pcFormConfig.value.currentItem = {};
  pcFormConfig.value.formItems = formConfig.formItemList ?? [];

  if (mobileConfig.formConfig && JSON.stringify(mobileConfig.formConfig) != '{}') {
    mobileFormConfig.value.config = mobileConfig.formConfig;
  }
  mobileFormConfig.value.currentItem = {};
  mobileFormConfig.value.formItems = mobileConfig.formItemList ?? [];

  formConfig.value = equipmentType.value == '1' ? pcFormConfig.value : mobileFormConfig.value;
};

// 清除表单模板绑定的字段
const clearFormTemplateFieldCode = arr => {
  if (arr?.length > 0) {
    arr.forEach(item => {
      item.fieldCode = undefined;
      if (item.children?.length > 0) {
        clearFormTemplateFieldCode(item.children);
      }
    });
  }
};

// 判断fieldCode是否为空
const judgeFieldCodeEmpty = () => {
  if (isFieldCodeEmpty(pcFormConfig, 'PC端') || isFieldCodeEmpty(mobileFormConfig, '移动端')) {
    return false;
  }
  return true;
};

/**
 * 判断字段代码是否为空
 * @param {Object} formConfig - 表单配置对象
 * @param {string} platform - 平台名称（PC端或移动端）
 * @returns {boolean} - 是否有效
 */
const isFieldCodeEmpty = (formConfig, platform) => {
  if (
    isParamEmpty(
      formConfig.value.formItems,
      'fieldCode',
      ['title', 'divide-line', 'pure-text', 'carousel', 'breadcrumb', 'grid', 'col'],
      'componentCode'
    )
  ) {
    message.warn(`【${platform}】存在未绑定的属性,请绑定后再操作！`);
    return true;
  }
  return false;
};

// 升级并保存
const upgradeAndSave = () => {
  loading.value = true;
  if (judgeFieldCodeEmpty()) {
    loading.value = true;
    FormDesignApi.upgradeModel({ formModelId: formModelId.value })
      .then(res => {
        formDefinitionId.value = res.data.formDefinitionId;
        // 替换路由参数
        router.push({
          query: { ...route.query, formDefinitionId: formDefinitionId.value }
        });
        save('update');
      })
      .finally(() => (loading.value = false));
  } else {
    loading.value = false;
  }
};

// 保存
const save = (type = '') => {
  loading.value = true;
  setmobileFormConfig();
  if (judgeFieldCodeEmpty()) {
    if (!ruleRequired(pcFormConfig.value, '【PC端】') || !ruleRequired(mobileFormConfig.value, '【移动端】'))
      return (loading.value = false);
    // pc
    let pcSaveFormConfig = {
      formConfig: pcFormConfig.value.config,
      formItemList: pcFormConfig.value.formItems
    };

    // 移动端
    let mobileSaveFormConfig = {
      formConfig: mobileFormConfig.value.config,
      formItemList: mobileFormConfig.value.formItems
    };
    FormDesignApi.saveOrUpdateFormConfig({
      formConfig: pcSaveFormConfig,
      mobileFormConfig: mobileSaveFormConfig,
      formDefinitionId: formDefinitionId.value
    })
      .then(res => {
        if (res.code == '00000') {
          message.success(res.message);
          if (type) {
            getPcFormConfig();
            getMobileFormConfig();
          }
        }
      })
      .finally(() => (loading.value = false));
  } else {
    loading.value = false;
  }

  // 校验必填
  function ruleRequired(data, name) {
    // 下拉单选列表
    let selectArr = data.formItems.filter(
      item => item.componentCode == 'select' || item.componentCode == 'radio' || item.componentCode == 'checkbox'
    );
    let currentSelectData = selectArr.find(item => !item.formItemSelect.dictTypeId);
    if (currentSelectData) {
      message.warning(name + currentSelectData.itemLabelName + '的字典类型不能为空!');
      return false;
    }
    return true;
  }
};

// 清空表单列表
const clearAll = () => {
  formConfig.value.formItems = [];
  handleSetSelectItem({ componentCode: '' });
};

// 设置类型改变
const typeChange = val => {
  equipmentType.value = val;
  if (val == '1') {
    pcFormConfig.value.currentItem = {};
    pcFormConfig.value.activeKey = 1;
    formConfig.value = pcFormConfig.value;
  } else if (val == '2') {
    setmobileFormConfig();
    formConfig.value = mobileFormConfig.value;
  }
};

// 设置移动端表单配置，span改为24，去掉没有的组件
const setmobileFormConfig = () => {
  if (mobileFormConfig.value?.formItems?.length == 0) {
    mobileFormConfig.value = cloneDeep(pcFormConfig.value);
  }
  mobileFormConfig.value.currentItem = {};
  mobileFormConfig.value.activeKey = 1;
  let mobileComponentTypeList = formLeftRef.value.getMobileComponentTypeList();
  mobileFormConfig.value.formItems = setItem(mobileFormConfig.value.formItems);

  function setItem(arr) {
    if (arr?.length > 0) {
      for (let i = arr.length - 1; i >= 0; i--) {
        if (!mobileComponentTypeList.includes(arr[i].componentCode)) {
          arr.splice(i, 1);
        }
        if (arr[i]) arr[i].itemColumnNumber = 24;

        if (arr[i]?.children?.length > 0) {
          arr[i].children = setItem(arr[i].children);
        }
      }
    }
    return arr;
  }
};

// 单击控件时添加到面板中
const addItem = async element => {
  let formItem = cloneDeep(element);
  formItem.itemLabelName = formItem.componentName;
  await generateKey(formItem);
  setGlobalConfigState(formItem);
  formConfig.value.formItems.push(formItem);
  handleSetSelectItem(formItem);
};

// 设置每一个表单的配置
const setGlobalConfigState = formItem => {
  formItem.contentValidateType = 1; //内容校验类型：1-常用格式校验，2-基于正则表达式校验，3-基于js校验，4-基于后台接口校验
  formItem.formatType = null;
  formItem.validateErrorTip = '';
  formItem.regexExpression = '';
  formItem.jsValidateCode = '';
  formItem.backendValidateParamName = '';
  formItem.backendValidateUrl = '';
  formItem.placeholderContent = ''; // 站位符
  formItem.itemEditFlag = true; //是否可编辑
  formItem.itemHiddenFlag = false; //是否隐藏
  formItem.itemRequiredFlag = false; //必填项
  formItem.itemReadonlyFlag = false; //是否只读
  formItem.itemHeight = 0;
  formItem.itemLabelShowFlag = true; //标签是的显示
  formItem.itemMultipleChoiceFlag = false; //是否多选
  formItem.bindFieldFlag = true; // 是否绑定属性
  formItem.formViewConfig = {
    showSelectColumn: true,
    openQueryParam: false
  };
  formItem.formItemStyle = {
    marginTop: 0,
    marginBottom: 16,
    marginLeft: 0,
    marginRight: 0
  };
  // 数据加载的配置
  formItem.formItemDataLoad = {
    apiRequestParamList: [],
    apiUrl: '',
    dataLoadType: 1,
    httpMethod:  '',
    staticData: '',
    userInfoFieldName: '',
  }

  if (['title', 'table', 'divide-line', 'collapse', 'grid'].includes(formItem.componentCode) || equipmentType.value == '2') {
    formItem.itemColumnNumber = 24;
  } else {
    formItem.itemColumnNumber = globalConfigState.value.span;
  }
  // 下拉单选属性
  const componentCodeArr = ['select', 'radio', 'checkbox'];
  if (componentCodeArr.find(item => item == formItem.componentCode)) {
    formItem.formItemSelect = {
      dictValueType: 1
    };
  } else if (['custom-select', 'tree-select', 'tree', 'link-select', 'transfer', 'select-modal'].includes(formItem.componentCode)) {
    // 自定义下拉
    formItem.formItemSelect = {
      dataFromType: 1,
      valueType: 1
    };
  } else if (['title', 'divide-line', 'pure-text'].includes(formItem.componentCode)) {
    // 字体内容
    formItem.formItemContent = {
      fontSize: '16px',
      textAlign: 'left',
      fontColor: '#000',
      lineColor: '#000',
      lineHeight: '1px'
    };
    if (formItem.componentCode == 'divide-line') {
      formItem.formItemContent.lineHeight = '';
    }
  } else if (['view-select'].includes(formItem.componentCode)) {
    // 视图选择
    formItem.formItemView = {};
  } else if (['table', 'collapse'].includes(formItem.componentCode)) {
    formItem.children = [];
    if (formItem.componentCode == 'table') {
      formItem.formItemTable = {
        showDeleteFlag: true,
        showNumberFlag: true,
        showBorderFlag: true,
        defaultRowNumber: null,
        showAddFlag: true
      };
    }
  } else if (['number', 'dashboard'].includes(formItem.componentCode)) {
    // 数字
    formItem.formItemNumber = {};
  } else if (['upload', 'upload-pic'].includes(formItem.componentCode)) {
    formItem.formItemFile = {
      fileSizeLimitKb: null,
      fileTypeLimitList: [],
      maxUploadCount: null,
    };
  }  else if (['step'].includes(formItem.componentCode)) {
    formItem.formItemStep = [];
  } else if (['carousel'].includes(formItem.componentCode)) {
    formItem.formItemCarouselList = [];
  } else if (['breadcrumb'].includes(formItem.componentCode)) {
    formItem.formItemBreadcrumbList = [];
  } else if (['modal-prompt'].includes(formItem.componentCode)) {
    formItem.formItemDialog = {
      dialogHiddenFlag: true,
      content: ''
    };
  } else if (['date', 'datetime'].includes(formItem.componentCode)) {
    formItem.formItemDate = {};
  } else if (['grid'].includes(formItem.componentCode)) {
    formItem.gutter = 12;
    formItem.children = [
      {
        itemId: getUUID(19),
        itemColumnNumber: 12,
        componentCode: 'col',
        children: []
      },
      {
        itemId: getUUID(19),
        itemColumnNumber: 12,
        componentCode: 'col',
        children: []
      }
    ];
  }
};

// 设置表单属性
const setFormConfig = config => {
  formConfig.value = config;
};

/**
 * 选中表单项
 * @param record 当前选中的表单项
 */
const handleSetSelectItem = record => {
  if (!record?.formViewConfig) {
    record.formViewConfig = {
      showSelectColumn: true,
      openQueryParam: false
    };
  }

  formConfig.value.currentItem = record;
  handleChangePropsTabs(record.itemId ? (formConfig.value.activeKey === 1 ? 1 : formConfig.value.activeKey) : 1);
};

/**
 * 切换属性面板
 * @param key
 */
const handleChangePropsTabs = key => {
  formConfig.value.activeKey = key;
};

/**
 * 复制或者添加表单，isCopy为true时则复制表单
 * @param item 当前点击的组件
 * @param isCopy {boolean} 是否复制
 */
const handleCopy = (item = formConfig.value.currentItem, isCopy = true) => {
  const itemId = formConfig.value.currentItem?.itemId;
  /**
   * 遍历当表单项配置，如果是复制，则复制一份表单项，如果不是复制，则直接添加到表单项中
   * @param formItems
   */
  const traverse = formItems => {
    // 使用some遍历，找到目标后停止遍历
    formItems.some((formItem, index) => {
      if (formItem.itemId === itemId) {
        // 判断是不是复制
        isCopy ? formItems.splice(index, 0, copyFormItem(formItem)) : formItems.splice(index + 1, 0, item);
        const event = {
          newIndex: index + 1
        };
        // 添加到表单项中
        handleBeforeColAdd(event, formItems, isCopy);
        return true;
      } else if (formItem?.children) {
        traverse(formItem.children);
      }
      if (['tabs'].includes(formItem.componentCode)) {
        // 栅格布局
        formItem.columns?.forEach(item => {
          traverse(item.children);
        });
      }
    });
  };
  traverse(formConfig.value.formItems);
};

/**
 * 复制表单项，如果表单项为栅格布局，则遍历所有自表单项重新生成key
 * @param formItem
 * @return
 */
const copyFormItem = formItem => {
  const newFormItem = cloneDeep(formItem);
  if (newFormItem.componentCode === 'grid') {
    formItemsForEach([formItem], async item => {
      await generateKey(item);
    });
  }
  return newFormItem;
};

/**
 * 添加到表单中
 * @param newIndex {object} 事件对象
 * @param formItems {} 表单项列表
 * @param isCopy {boolean} 是否复制
 */
const handleBeforeColAdd = async ({ newIndex }, formItems, isCopy = false) => {
  const item = formItems[newIndex];
  isCopy && (await generateKey(item));
  handleSetSelectItem(item);
};

// 刷新字典
const refreshDict = async flag => {
  dictTypeList.value = await MetaUserDictApi.getDictTypeList();
  if (flag) {
    message.success('刷新成功');
  }
};

// 把表单配置项注入到子组件中，子组件可通过inject获取，获取到的数据为响应式
provide('formConfig', formConfig);

// 把祖先组件的方法项注入到子组件中，子组件可通过inject获取
provide('formDesignMethods', {
  handleCopy,
  addItem,
  handleSetSelectItem,
  setFormConfig
});

provide('bindFieldList', bindFieldList);
provide('selectSheetList', selectSheetList);
provide('dictTypeList', dictTypeList);
provide('refreshDict', refreshDict);
provide('viewSelectList', viewSelectList);
provide('formRef', null);
</script>

<style lang="less">
@import url('./style/form-design.less');
</style>
