<template>
  <a-tabs v-model:activeKey="activeKey">
    <a-tab-pane
      v-for="(pane, index) in props.config.panes"
      :key="index"
      :tab="pane.title + (pane.count ? `(${pane.total})` : '')"
    >
      <div class="box relative" v-if="activeKey == index">
        <div class="button-box" v-if="pane.type === TableType.FORM">
          <div class="item create" @click="openCreate" v-if="pane.isShowAdd">新增数据</div>
          <div class="search" @click="showSearch"
            >查询 <BasicArrow class="ml-1" :expand="!searchData.show" up
          /></div>
        </div>
        <div class="search-box" v-if="searchData.show">
          <SearchBox
            v-if="searchData.show"
            :formSchema="searchData.formSchema"
            :fieldMapToTime="searchData.fieldMapToTime"
            @search="SearchFormTableList"
          />
        </div>
        <div class="button-box" v-if="pane.type === TableType.API && pane.associatedForm">
          <div class="item create" @click="openCreate" v-if="pane.isShowAdd">新增数据</div>
        </div>
        <div
          class="content"
          v-if="state.dataSource.length > 0"
          :style="{ height: pane.isShowAdd ? 'calc(100% - 46px)' : 'calc(100% - 20px)' }"
        >
          <a-table
            :key="pane.key"
            :data-source="state.dataSource"
            :columns="state.columns"
            :pagination="{
              pageSize: pane.pageSize,
              total: pane.total,
            }"
            position="bottomRight"
            :rowKey="pane.primaryKey ? pane.primaryKey : 'id'"
            :customRow="customRow"
            :row-selection="rowSelection"
            size="small"
            @change="
              (v) => {
                changePage(pane, v);
              }
            "
          >
            <template #bodyCell="{ column, record }">
              <template v-if="column.dataIndex === 'operation'">
                <span class="edit-icon" @click.stop="onEdit(record)">编辑</span>
                <a-popconfirm title="确定删除?" @confirm="onDelete(record)">
                  <span class="delete-icon" @click.stop="">删除</span>
                </a-popconfirm>
              </template>
            </template>
          </a-table>
        </div>
        <EmptyBox v-else />
        <ModalPanel
          v-if="modalData.modalOpen"
          :visible="modalData.modalOpen"
          :title="modalData.title"
          @submit="modalSubmit"
          @close="modalClose"
        >
          <SimpleForm
            v-if="modalData.modalOpen && pane.formType == FormTypeEnum.CUSTOM_FORM"
            :ref="setItemRef"
            :formProps="modalData.formProps"
            :formModel="modalData.formModel"
          />
          <DesktopForm
            v-else-if="modalData.modalOpen && pane.formType == FormTypeEnum.SYSTEM_FORM"
            :ref="setItemRef"
            :systemComponent="pane.systemComponent"
            :formModel="modalData.formModel"
          />
        </ModalPanel>
      </div>
    </a-tab-pane>
  </a-tabs>
</template>

<script setup lang="ts">
  import { computed, inject, onMounted, reactive, ref, watch } from 'vue';
  import { TabsTableProperties } from '../config/properties';
  import { DesktopComponent, TableType } from '/@/enums/desktop';
  import { TableColumnItem, TabsTableConfig } from '/@/model/desktop/designer';
  import { cloneDeep } from 'lodash-es';

  import { getComplexPage } from '/@/api/form/execute';
  import { getFormRelease } from '/@/api/form/release';
  import { ModalPanel } from '/@/components/ModalPanel/index';
  import SimpleForm from '/@/components/SimpleForm/src/SimpleForm.vue';
  import { buildOption } from '/@/utils/helper/designHelper';
  import {
    addComplexFormExecute,
    editComplexFormExecute,
    getComplexInfo,
    getComplexQuery,
  } from '/@/api/form/design/index';
  import { getFormTemplate, deleteComplex } from '/@/api/form/design';
  import { notification } from 'ant-design-vue';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { FormTypeEnum } from '/@/enums/formtypeEnum';
  import { nextTick } from 'vue';
  import { QueryConfig } from '/@/model/generator/listConfig';
  import { whetherNeedToTransform, findSchema } from '/@/utils/helper/generatorHelper';
  import { ComponentOptionModel } from '/@/model/generator/codeGenerator';
  import useComplexApiRequest from './../../../hooks/useComplexApiRequest';
  import { FormSchema } from '/@/components/Table';
  import { handleSearchForm } from '/@/utils/helper/exportHelper';
  import SearchBox from './table/Search.vue';
  import { BasicArrow } from '/@/components/Basic';
  import { FieldMapToTime } from '/@/components/Form/src/types/form';
  import { EmptyBox } from '/@/components/ModalPanel/index';
  import { DesktopForm } from '/@/components/SystemForm/index';
  interface SearchDate {
    fieldName: string;
    format: string;
  }
  const searchData: {
    formSchema: FormSchema[];
    fieldMapToTime: FieldMapToTime;
    params: { [x: string]: any };
    show: Boolean;
  } = reactive({
    formSchema: [],
    show: false,
    fieldMapToTime: [],
    params: {},
  });

  const { changeApiOptions } = useComplexApiRequest();
  const changeDataDisplay = inject('changeDataDisplay') as any;
  const enum ActionType {
    ADD = 0,
    EDIT = 1,
  }
  const { t } = useI18n();
  let itemRefs = ref([]) as any;
  const setItemRef = (el: never) => {
    if (el) {
      itemRefs.value.push(el);
    }
  };
  const props = withDefaults(
    defineProps<{
      type: DesktopComponent;
      id: string;
      w: number;
      h: number;
      title: string;
      config: TabsTableConfig;
      changeDataKey?: number;
    }>(),
    {
      type: DesktopComponent.TABLE,
      w: 0,
      h: 0,
      id: '',
      config: () => {
        return TabsTableProperties;
      },
    },
  );
  watch(
    () => props.config.renderKey,
    (val) => {
      val && resizeLayout();
    },
  );
  watch(
    () => props.changeDataKey,
    (val) => {
      val && changeData();
    },
  );
  const modalData = reactive({
    type: ActionType.ADD,
    title: '新增',
    modalOpen: false,
    pkValue: '',
    formModel: {},
    formProps: {},
  });
  const activeKey = ref(0);
  const rowSelection = computed(() => {
    return {
      checkStrictly: true,
      type: 'radio',
      selectedRowKeys: state.selectedRowKeys,
      onChange: (_selectedRowKeys: string[], selectedRows) => {
        let record = selectedRows[0];
        changeTableInfo(record);
      },
    };
  });
  const customRow = (record) => {
    return {
      onClick: () => {
        changeTableInfo(record);
      },
    };
  };
  const state: {
    dataSource: Array<any>;
    columns: Array<TableColumnItem>;
    selectedRowKeys: Array<string>;
  } = reactive({ dataSource: [], columns: [], selectedRowKeys: [] });

  watch(
    () => activeKey.value,
    () => {
      resizeLayout();
    },
  );
  onMounted(() => {
    resizeLayout();
  });

  function changeTableInfo(record) {
    const primaryKey = props.config.panes[activeKey.value].primaryKey || '';
    if (state.selectedRowKeys.includes(record[primaryKey])) {
      state.selectedRowKeys = [];
      if (props.id) {
        let tableRecord = window.localStorage.getItem('TableRecord');
        if (tableRecord) {
          let tableRecordList = JSON.parse(tableRecord);
          tableRecordList[props.id] = null;
          window.localStorage.setItem('TableRecord', JSON.stringify(tableRecordList));
        }
      }
    } else {
      state.selectedRowKeys = [record[primaryKey]];

      if (props.id) {
        let tableRecord = window.localStorage.getItem('TableRecord');
        if (tableRecord) {
          let tableRecordList = JSON.parse(tableRecord);
          tableRecordList[props.id] = record;
          window.localStorage.setItem('TableRecord', JSON.stringify(tableRecordList));
        } else {
          let list = {};
          list[props.id] = record;

          window.localStorage.setItem('TableRecord', JSON.stringify(list));
        }
      }
    }
    if (changeDataDisplay) changeDataDisplay();
  }
  async function changeData() {
    if (props.config.panes) {
      let panes = props.config.panes[activeKey.value];
      if (panes.type === TableType.API) {
        if (panes.apiConfig && panes.apiConfig.path) {
          let res = await changeApiOptions(panes.apiConfig);
          if (res.list) {
            state.dataSource = res.list;
          } else {
            state.dataSource = [];
          }
          panes.total = res.total || 0;
        }
      } else {
        if (panes.releaseId) {
          // 搜索
          let releaseResult = await getFormRelease(panes.releaseId);
          const configJson = JSON.parse(releaseResult.configJson);
          const { queryConfigs } = configJson.listConfig!;
          let searchFormSchema: FormSchema[] = []; //搜索框配置
          let searchDate: SearchDate[] = [];
          //获取表单模板数据
          const templateResult = await getFormTemplate(releaseResult.formId);
          const formJson = JSON.parse(templateResult.formJson);
          //构建表单Props
          let formProps = buildOption(formJson.formJson, false);

          //查询配置转换为schema
          [searchFormSchema, searchDate] = ConvertQueryConfigToFormSchema(
            queryConfigs,
            formProps.schemas!,
            formJson.formJson.list,
          );
          searchData.formSchema = searchFormSchema;
          const fieldMapToTime: FieldMapToTime = searchDate.map((date) => {
            return [
              date.fieldName!,
              [date.fieldName + 'Start', date.fieldName + 'End'],
              date.format,
              true,
            ];
          });
          searchData.fieldMapToTime = fieldMapToTime;
        } else {
          if (panes.formId) {
            let queryConfigs = await getComplexQuery(panes.formId);
            let searchFormSchema: FormSchema[] = []; //搜索框配置
            let searchDate: SearchDate[] = [];
            //获取表单模板数据
            const templateResult = await getFormTemplate(panes.formId);
            const formJson = JSON.parse(templateResult.formJson);
            //构建表单Props
            let formProps = buildOption(formJson.formJson, false);

            //查询配置转换为schema
            [searchFormSchema, searchDate] = ConvertQueryConfigToFormSchema(
              queryConfigs,
              formProps.schemas!,
              formJson.formJson.list,
            );
            searchData.formSchema = searchFormSchema;
            const fieldMapToTime: FieldMapToTime = searchDate.map((date) => {
              return [
                date.fieldName!,
                [date.fieldName + 'Start', date.fieldName + 'End'],
                date.format,
                true,
              ];
            });
            searchData.fieldMapToTime = fieldMapToTime;
          }
        }
        // 列表
        await SearchFormTableList(null);
      }
    }
  }
  async function SearchFormTableList(data = null) {
    if (!props.config.panes) return;
    try {
      let panes = props.config.panes[activeKey.value];
      if (panes.formId) {
        let params = {};
        searchData.params = {};
        if (data) {
          params = { params: data };
          searchData.params = data;
        }

        let paramsData = {
          limit: panes.current,
          releaseId: panes.releaseId,
          formId: panes.formId,
          size: panes.pageSize,
          ...params,
        };
        if (
          ((panes.formType === FormTypeEnum.CUSTOM_FORM && panes.releaseId) ||
            panes.formType === FormTypeEnum.SYSTEM_FORM) &&
          panes.formId
        ) {
          let res = await getComplexPage(paramsData);
          panes.total = res.total;
          if (res.list) {
            state.dataSource = res.list;
          } else {
            state.dataSource = [];
          }
        }
      }
    } catch (error) {}
    searchData.show = false;
  }
  /**
   * QueryConfig 转换 为搜索栏 FormSchema
   * 根据查询字段 获取到 当前字段查询组件的类型
   * 普通类型：input
   * 远程组件：ApiSelect
   * 时间字段：RangePicker
   */
  function ConvertQueryConfigToFormSchema(
    queryConfigs: QueryConfig[],
    schemas: FormSchema[],
    list: ComponentOptionModel[],
  ): [FormSchema[], SearchDate[]] {
    const searchDate: SearchDate[] = [];
    if (!queryConfigs) {
      return [[], []];
    }
    const searchFormSchema = queryConfigs.map((config) => {
      if (!!config.isDate) {
        searchDate.push({
          fieldName: config.fieldName,
          format: config.format!,
        });
      }
      const schema = findSchema(schemas, config.fieldName);
      const [isNeedTrans, option] = whetherNeedToTransform(config, list);

      return handleSearchForm(option, schema, config, isNeedTrans, false) as FormSchema;
    });
    return [searchFormSchema, searchDate];
  }
  async function showList() {
    if (!props.config.panes) return;
    let panes = props.config.panes[activeKey.value];
    if (panes.columns) {
      state.columns = cloneDeep(panes.columns).filter((ele) => {
        return ele.show;
      });
    }
    if ((panes.type === TableType.API && panes.associatedForm) || panes.type === TableType.FORM) {
      state.columns.push({
        title: '操作',
        dataIndex: 'operation',
        show: true,
        width: 80,
      });
    }
    await changeData();
  }
  async function onDelete(record) {
    if (!props.config.panes) return;
    let panes = props.config.panes[activeKey.value];
    try {
      if (!panes.primaryKey || !panes.formId || !record[panes.primaryKey]) {
        return false;
      }
      let res = await deleteComplex({
        formId: panes.formId,
        pkName: panes.primaryKey,
        pkValue: record[panes.primaryKey],
      });
      if (res) {
        notification.success({
          message: t('提示'),
          description: t('删除成功！'),
        }); //提示消息
        panes.current = 1;
        await showList();
      } else {
        notification.error({
          message: t('提示'),
          description: t('删除失败！'),
        }); //提示消息
      }
    } catch (error) {}
  }
  async function onEdit(record) {
    if (!props.config.panes) return;
    let panes = props.config.panes[activeKey.value];
    if (!panes.primaryKey) {
      return false;
    }
    if (panes.formId) {
      modalData.type = ActionType.EDIT;
      modalData.modalOpen = true;
      modalData.title = '编辑数据';
      modalData.pkValue = record[panes.primaryKey];

      try {
        if (panes.formType == FormTypeEnum.SYSTEM_FORM) {
          // 系统表单直接走页面的formModel
          modalData.formModel = cloneDeep(record);
        } else {
          const templateResult = await getFormTemplate(panes.formId);
          const formJson = JSON.parse(templateResult.formJson);
          let formProps = buildOption(formJson.formJson, false);
          modalData.formProps = formProps;
          let formData = await getComplexInfo({
            formId: panes.formId,
            pkValue: modalData.pkValue,
            pkName: panes.primaryKey,
          });
          await nextTick();
          await itemRefs.value[activeKey.value]?.setFieldsValue(formData);
        }
      } catch (error) {
        console.log('error: ', error);
      }
    } else {
      console.log('你未选择表单');
    }
  }
  function resizeLayout() {
    if (props.config.panes) {
      let panes = props.config.panes[activeKey.value];
      panes.current = 1;
      panes.pageSize = panes.pageSize || 20;
      panes.total = 0;
      showList();
    }
  }
  async function openCreate() {
    if (!props.config.panes) return;
    let panes = props.config.panes[activeKey.value];
    modalData.formModel = {};
    if (panes.formId) {
      modalData.type = ActionType.ADD;
      modalData.modalOpen = true;
      modalData.title = '新增数据';
      try {
        const templateResult = await getFormTemplate(panes.formId);
        const formJson = JSON.parse(templateResult.formJson);
        let formProps = buildOption(formJson.formJson, false);
        modalData.formProps = formProps;
      } catch (error) {
        console.log('error: ', error);
      }
    } else {
      console.log('你未选择表单');
    }
  }
  async function modalSubmit() {
    if (!props.config.panes) return;
    let panes = props.config.panes[activeKey.value];
    try {
      if (panes.formType == FormTypeEnum.SYSTEM_FORM) {
        // 系统表单直接走页面的formModel
        await itemRefs.value[activeKey.value]?.submit();
      } else {
        const values = await itemRefs.value[activeKey.value]?.validate();
        if (modalData.type == ActionType.ADD) {
          await addComplexFormExecute(panes.formId, values);
          notification.success({
            message: t('提示'),
            description: t('新增成功！'),
          }); //提示消息
        } else {
          if (panes.primaryKey && panes.formId) {
            values[panes.primaryKey] = modalData.pkValue;
            await editComplexFormExecute({
              formId: panes.formId,
              formData: values,
              pkName: panes.primaryKey,
            });
            notification.success({
              message: t('提示'),
              description: t('编辑成功！'),
            }); //提示消息
          } else {
            notification.error({
              message: t('提示'),
              description: t('表单或表单主键不存，编辑失败！'),
            });
          }
        }
      }

      modalData.modalOpen = false;
      itemRefs.value = [];
      panes.current = 1;
      await showList();
    } catch (error) {
      console.log('error: ', error);
    }
  }
  function showSearch() {
    // 处理数据
    initSearchBox();
    searchData.show = !searchData.show;
  }
  function initSearchBox() {
    // 时间日期特殊字段处理
    let timeParams = {};
    if (searchData.fieldMapToTime.length > 0) {
      searchData.fieldMapToTime.forEach((element) => {
        if (element[1] && Array.isArray(element[1])) {
          if (
            element[1][0] &&
            element[1][1] &&
            searchData.params[element[1][0]] &&
            searchData.params[element[1][1]]
          ) {
            timeParams[element[0]] = [
              searchData.params[element[1][0]],
              searchData.params[element[1][1]],
            ];
          }
        }
      });
    }
    // 默认值赋值
    for (const key in searchData.formSchema) {
      if (Object.prototype.hasOwnProperty.call(searchData.formSchema, key)) {
        const element = searchData.formSchema[key];
        if (timeParams[element.field]) {
          element.defaultValue = timeParams[element.field];
        } else {
          element.defaultValue = searchData.params[element.field];
        }
      }
    }
  }
  function modalClose() {
    modalData.modalOpen = false;
    itemRefs.value = [];
  }
  async function changePage(pane, pagenation) {
    pane.current = pagenation.current;
    await showList();
  }
</script>

<style lang="less" scoped>
  :deep(.ant-tabs-nav) {
    margin: 0;
  }

  :deep(.ant-tabs-tab) {
    padding: 10px;

    & + .ant-tabs-tab {
      margin-left: 0;
    }
  }

  :deep(.ant-tabs-content) {
    height: 100%;
  }

  .box {
    height: 100%;

    .item-title {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 50px;
      line-height: 50px;
      color: #262626;
      font-size: 14px;
      padding-left: 16px;
    }

    .content {
      padding: 0 20px;
      overflow: hidden;
      height: calc(100% - 46px);

      :deep(.ant-table) {
        height: calc(100% - 50px);
        overflow: auto;
      }

      :deep(.ant-spin-container),
      :deep(.ant-table-container),
      :deep(.ant-table-content),
      .ant-table-wrapper {
        height: 100%;
      }

      :deep(.ant-table-tbody) {
        overflow-y: scroll;
        height: calc(100% - 40px);
      }
    }
  }

  .page-box {
    position: absolute;
    right: 30px;
    bottom: 10px;
  }

  .button-box {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 10px;

    .item {
      font-size: 14px;
      padding: 2px 10px;
      margin-right: 10px;
      cursor: pointer;
    }

    .create {
      border-radius: 4px;
      color: #fff;
      background-color: #39f;
    }

    .search {
      font-size: 14px;
      color: #39f;
      cursor: pointer;
    }
  }

  .search-box {
    position: absolute;
    top: 40px;
    left: 2px;
    right: 2px;
    background-color: #fff;
    z-index: 2;
    border: 1px solid rgb(204 204 204 / 47%);
    box-shadow: 1px 2px 10px #ccc;
    padding: 0 10px;
    padding-top: 40px;
    margin: 4px;
  }

  :deep(.ant-table-pagination.ant-pagination) {
    position: absolute;
    margin: 0;
    right: 0;
  }
</style>
