<template>
  <div ref="wrapRef" :class="getWrapperClass">
    <BasicForm
      class="search-form-erp"
      :style="{ width: advanceRight ? '100%' : tabelWidth - calcToolBarWidth - 10 + 'px' }"
      ref="formRef"
      submitOnReset
      v-bind="{ ...getFormProps, tableWidth: tabelWidth, toolBarWidth: calcToolBarWidth }"
      v-if="getBindValues.useSearchForm"
      :tableAction="tableAction"
      @register="registerForm"
      @submit="handleSearchInfoChange"
    >
      <template #[replaceFormSlotKey(item)]="data" v-for="item in getFormSlotKeys">
        <slot :name="item" v-bind="data || {}"></slot>
      </template>
    </BasicForm>
    <div
      :style="{
        height: '100%',
        background: '#fff',
      }"
    >
      <a-table
        class="basic-erp-table"
        ref="tableElRef"
        v-bind="getBindValues"
        :rowClassName="getRowClassName"
        v-show="getEmptyDataIsShowTable"
        :showSorterTooltip="false"
        @change="handleTableChange"
      >
        <template #summary v-if="columns.filter((x) => x.total).length > 0">
          <a-table-summary-row>
            <a-table-summary-cell>合计</a-table-summary-cell>
            <a-table-summary-cell v-if="getBindValues.rowSelection" />
            <a-table-summary-cell
              v-for="(column, idx) in columns.filter((x) => {
                return !getBindValues.showIndexColumn
                  ? x.flag !== 'ACTION'
                  : x.flag !== 'INDEX' && x.flag !== 'ACTION';
              })"
              :key="idx"
              :style="{ textAlign: column.align }"
            >
              <a-typography-text v-if="column.total" keyboard>
                {{
                  sum(getBindValues.dataSource.map((x) => Number(x[column.dataIndex as string])))
                }}
              </a-typography-text>
            </a-table-summary-cell>
            <a-table-summary-cell v-if="getBindValues.actionColumn" />
          </a-table-summary-row>
        </template>
        <template #[item]="data" v-for="item in Object.keys($slots)" :key="item">
          <slot :name="item" v-bind="data || {}"></slot>
        </template>

        <template #bodyCell="data">
          <template v-for="item in Object.keys($slots)">
            <slot
              v-if="data.column && data.column.dataIndex && data.column.dataIndex === item"
              :name="item"
              v-bind="data || {}"
            ></slot>
          </template>
        </template>

        <template #headerCell="{ column }">
          <HeaderCell :column="column" />
        </template>
      </a-table>
    </div>
  </div>
</template>
<script lang="ts">
  import type {
    BasicTableProps,
    TableActionType,
    SizeType,
    ColumnChangeParam,
  } from './types/table';

  import {
    defineComponent,
    ref,
    computed,
    unref,
    toRaw,
    inject,
    watchEffect,
    defineAsyncComponent,
  } from 'vue';
  import { useForm } from '/@/components/Form/index';
  const BasicForm = defineAsyncComponent(() => import('/@/components/Form/src/BasicForm.vue'));
  import { PageWrapperFixedHeightKey } from '/@/components/Page';
  import HeaderCell from './components/HeaderCell.vue';
  import { InnerHandlers } from './types/table';
  import { usePagination } from './hooks/usePagination';
  import { useColumns } from './hooks/useColumns';
  import { useDataSource } from './hooks/useDataSource';
  import { useLoading } from './hooks/useLoading';
  import { useRowSelection } from './hooks/useRowSelection';
  import { useTableScroll } from './hooks/useTableScroll';
  import { useTableScrollTo } from './hooks/useScrollTo';
  import { useCustomRow } from './hooks/useCustomRow';
  import { useTableStyle } from './hooks/useTableStyle';
  import { useTableHeaderErp } from './hooks/useTableHeaderErp';
  import { useTableExpand } from './hooks/useTableExpand';
  import { createTableContext } from './hooks/useTableContext';
  import { useTableFooter } from './hooks/useTableFooter';
  import { useTableForm } from './hooks/useTableForm';
  import { useDesign } from '/@/hooks/web/useDesign';

  import { omit, sum } from 'lodash-es';
  import { basicProps } from './props';
  import { isFunction } from '/@/utils/is';
  import { warn } from '/@/utils/log';
  import { useI18n } from '/@/hooks/web/useI18n';

  export default defineComponent({
    components: {
      BasicForm,
      HeaderCell,
    },
    props: basicProps,
    emits: [
      'fetch-success',
      'fetch-error',
      'selection-change',
      'register',
      'row-click',
      'row-dbClick',
      'row-contextmenu',
      'row-mouseenter',
      'row-mouseleave',
      'edit-end',
      'edit-cancel',
      'edit-row-end',
      'edit-change',
      'expanded-rows-change',
      'change',
      'columns-change',
    ],
    setup(props, { attrs, emit, slots, expose }) {
      const { t } = useI18n();
      const tableElRef = ref(null);
      const tableData = ref<Recordable[]>([]);
      const wrapRef = ref(null);
      const formRef = ref();
      const innerPropsRef = ref<Partial<BasicTableProps>>();
      const { prefixCls } = useDesign('basic-table');
      const [registerForm, formActions] = useForm();

      const getProps = computed(() => {
        return { ...props, ...unref(innerPropsRef) } as BasicTableProps;
      });
      const title = ref(props.title);
      const isFixedHeightPage = inject(PageWrapperFixedHeightKey, false);
      watchEffect(() => {
        unref(isFixedHeightPage) &&
          props.canResize &&
          warn(
            "'canResize' of BasicTable may not work in PageWrapper with 'fixedHeight' (especially in hot updates)",
          );
      });

      const { getLoading, setLoading } = useLoading(getProps);
      const {
        getPaginationInfo,
        getPagination,
        setPagination,
        setShowPagination,
        getShowPagination,
      } = usePagination(getProps);

      const {
        getRowSelection,
        getRowSelectionRef,
        getSelectRows,
        clearSelectedRowKeys,
        getSelectRowKeys,
        deleteSelectRowByKey,
        setSelectedRowKeys,
      } = useRowSelection(getProps, tableData, emit);

      const {
        handleTableChange: onTableChange,
        getDataSourceRef,
        getDataSource,
        getRawDataSource,
        setTableData,
        updateTableDataRecord,
        deleteTableDataRecord,
        insertTableDataRecord,
        findTableDataRecord,
        fetch,
        getRowKey,
        reload,
        getAutoCreateKey,
        updateTableData,
      } = useDataSource(
        getProps,
        {
          tableData,
          getPaginationInfo,
          setLoading,
          setPagination,
          getFieldsValue: formActions.getFieldsValue,
          clearSelectedRowKeys,
        },
        emit,
      );

      function handleTableChange(...args) {
        const { onChange, isPaginateByDataSource, isFilterByDataSoure } = unref(getProps);
        if (args[3].action === 'filter' && isFilterByDataSoure) return;

        onTableChange.call(undefined, isPaginateByDataSource, ...args);
        emit('change', ...args);

        // 解决通过useTable注册onChange时不起作用的问题
        onChange && isFunction(onChange) && onChange.call(undefined, ...args);
      }

      const {
        getViewColumns,
        getColumns,
        setCacheColumnsByField,
        setColumns,
        getColumnsRef,
        getCacheColumns,
      } = useColumns(getProps, getPaginationInfo);

      const { getScrollRef, redoHeight, tabelWidth } = useTableScroll(
        getProps,
        tableElRef,
        getColumnsRef,
        getRowSelectionRef,
        getDataSourceRef,
        wrapRef,
        formRef,
      );

      const { scrollTo } = useTableScrollTo(tableElRef, getDataSourceRef);

      const { customRow } = useCustomRow(getProps, {
        setSelectedRowKeys,
        getSelectRowKeys,
        clearSelectedRowKeys,
        getAutoCreateKey,
        emit,
      });

      const { getRowClassName } = useTableStyle(getProps, prefixCls);

      const { getExpandOption, expandAll, expandRows, collapseAll } = useTableExpand(
        getProps,
        tableData,
        emit,
      );

      const handlers: InnerHandlers = {
        onColumnsChange: (data: ColumnChangeParam[]) => {
          emit('columns-change', data);
          // support useTable
          unref(getProps).onColumnsChange?.(data);
        },
      };

      const { getHeaderProps, calcToolBarWidth } = useTableHeaderErp(
        getProps,
        slots,
        handlers,
        tableElRef,
      );

      const { getFooterProps } = useTableFooter(
        getProps,
        getScrollRef,
        tableElRef,
        getDataSourceRef,
      );

      const advanceRight = computed(() => {
        if (!formRef.value) return false;
        let advanceState = formRef.value!.advanceState;
        if (advanceState.isAdvanced && !advanceState.hideAdvanceBtn) {
          return true;
        } else {
          return false;
        }
      });
      const { getFormProps, replaceFormSlotKey, getFormSlotKeys, handleSearchInfoChange } =
        useTableForm(getProps, slots, fetch, getLoading);

      const getBindValues = computed(() => {
        const dataSource = unref(getDataSourceRef);

        let propsData: Recordable = {
          ...attrs,
          customRow,
          ...unref(getProps),
          ...unref(getHeaderProps),
          scroll: unref(getScrollRef),
          loading: unref(getLoading),
          tableLayout: 'fixed',
          rowSelection: unref(getRowSelectionRef),
          rowKey: unref(getRowKey),
          columns: toRaw(unref(getViewColumns)),
          pagination: toRaw(unref(getPaginationInfo)),
          dataSource,
          footer: unref(getFooterProps),
          ...unref(getExpandOption),
        };
        if (slots.expandedRowRender) {
          propsData = omit(propsData, 'scroll');
        }

        propsData = omit(propsData, ['class', 'onChange']);
        return propsData;
      });

      const getWrapperClass = computed(() => {
        const values = unref(getBindValues);
        let page = getShowPagination() ? prefixCls + '-form-has-pagenation' : '';

        return [
          prefixCls,
          attrs.class,
          {
            [`${prefixCls}-form-container`]: values.useSearchForm,
            [`${prefixCls}--inset`]: values.inset,
          },
          page,
        ];
      });

      const getEmptyDataIsShowTable = computed(() => {
        const { emptyDataIsShowTable, useSearchForm } = unref(getProps);
        if (emptyDataIsShowTable || !useSearchForm) {
          return true;
        }
        return !!unref(getDataSourceRef).length;
      });

      function setProps(props: Partial<BasicTableProps>) {
        innerPropsRef.value = { ...unref(innerPropsRef), ...props };
      }

      const tableAction: TableActionType = {
        reload,
        getSelectRows,
        clearSelectedRowKeys,
        getSelectRowKeys,
        deleteSelectRowByKey,
        setPagination,
        setTableData,
        updateTableDataRecord,
        deleteTableDataRecord,
        insertTableDataRecord,
        findTableDataRecord,
        redoHeight,
        setSelectedRowKeys,
        setColumns,
        setLoading,
        getDataSource,
        getRawDataSource,
        setProps,
        getRowSelection,
        getPaginationRef: getPagination,
        getColumns,
        getCacheColumns,
        emit,
        updateTableData,
        setShowPagination,
        getShowPagination,
        setCacheColumnsByField,
        expandAll,
        expandRows,
        collapseAll,
        scrollTo,
        getSize: () => {
          return unref(getBindValues).size as SizeType;
        },
      };
      createTableContext({ ...tableAction, wrapRef, getBindValues });

      expose(tableAction);

      emit('register', tableAction, formActions);

      return {
        formRef,
        tableElRef,
        getBindValues,
        getLoading,
        registerForm,
        handleSearchInfoChange,
        getEmptyDataIsShowTable,
        handleTableChange,
        getRowClassName,
        wrapRef,
        tableAction,
        redoHeight,
        getFormProps: getFormProps as any,
        replaceFormSlotKey,
        getFormSlotKeys,
        getWrapperClass,
        columns: getViewColumns,
        sum,
        t,
        tabelWidth,
        title,
        calcToolBarWidth,
        advanceRight,
      };
    },
  });
</script>
<style lang="less">
  @border-color: #cecece4d;

  @prefix-cls: ~'@{namespace}-basic-table';

  [data-theme='dark'] {
    .ant-table-tbody > tr:hover.ant-table-row-selected > td,
    .ant-table-tbody > tr.ant-table-row-selected td {
      background-color: #262626;
    }
  }

  .@{prefix-cls} {
    max-width: 100%;
    height: 100%;

    &-row__striped {
      td {
        background-color: @app-content-background;
      }
    }

    &-form-container {
      padding: 0;
      margin-right: 8px;
      position: relative;

      .ant-form {
        padding: 8px 0 0;
        margin-bottom: 0;
        background-color: @component-background;
        border-radius: 2px;

        &.search-form-erp {
          position: absolute;
          height: 42px;
          top: 51px;
          z-index: 99;
          right: 7px;
          left: 0;
          width: 70%;

          .ant-row {
            display: flex !important;
          }

          .ant-form-item-label {
            label {
              max-width: 100px;
              overflow: hidden;
              text-overflow: ellipsis;
              display: block;
              line-height: 32px;
              margin-right: 8px;
            }
          }

          .advanceRow,
          .basicRow {
            width: auto;

            .ant-form-item-control-input {
              .ant-select,
              .ant-input-box {
                width: 160px;
              }

              .ant-picker {
                width: 290px;
              }
            }

            .ant-col {
              flex: initial;
              max-width: initial;
            }
          }

          .basicCol {
            position: initial;
          }

          .suspensionRow {
            .advanceRow {
              width: calc(100% - 248px);
            }

            .basicRow {
              width: calc(100% - 178px);
            }
          }
        }
      }
    }

    .ant-tag {
      margin-right: 0;
    }

    .ant-table-wrapper {
      padding: 6px 0 6px 6px;
      background-color: @component-background;
      border-radius: 2px;
      height: 100%;

      .ant-spin-container {
        height: 100%;
      }

      .ant-table-title {
        min-height: 40px;
        padding: 0 0 8px !important;
      }

      .ant-table.ant-table-bordered .ant-table-title {
        border: none !important;
      }
    }

    .wrap {
      .ant-table-wrapper {
        padding: 0;
      }
    }

    .basic-erp-table {
      .ant-table {
        width: 100%;
        overflow-x: hidden;
        height: 100%;

        // &.ant-table-layout-fixed {
        //   .ant-table-body {
        //     border-right: 1px solid #f0f0f0;
        //   }
        // }

        &-title {
          display: flex;
          padding: 8px 6px;
          border-bottom: none;
          justify-content: space-between;
          align-items: center;
        }

        &-container {
          height: calc(100% - 96px);
        }

        .ant-table-thead {
          th {
            &::before {
              display: none;
            }

            .ant-table-column-sorters {
              justify-content: flex-start;
              display: inline-flex;

              .ant-table-column-title {
                flex: initial;
              }
            }
          }
        }

        .ant-table-body {
          height: calc(100% - 48px) !important;
          max-height: none !important;

          .ant-table-summary {
            z-index: 0;
          }

          // table {
          //   height: 100%;
          // }
        }
        //.ant-table-tbody > tr.ant-table-row-selected td {
        //background-color: fade(@primary-color, 8%) !important;
        //}
        .ant-table-tbody {
          tr {
            td {
              padding: 10px 8px;
            }

            &:hover {
              td {
                background-color: #eef4ff;
              }
            }

            &.ant-table-placeholder {
              .ant-table-expanded-row-fixed::after {
                display: none;
              }

              &:hover {
                td {
                  background-color: transparent;
                }
              }
            }
          }
        }
      }
    }

    &-form-has-pagenation {
      .basic-erp-table {
        .ant-table {
          height: calc(100% - 38px);
        }
      }
    }

    .ant-pagination {
      margin: 10px 6px 0 0;
    }

    .ant-table-footer {
      padding: 0;

      .ant-table-wrapper {
        padding: 0;
      }

      table {
        border: none !important;
      }

      .ant-table-body {
        overflow-x: hidden !important;
        //  overflow-y: scroll !important;
      }

      td {
        padding: 12px 8px;
      }
    }

    &--inset {
      .ant-table-wrapper {
        padding: 0;
      }
    }
  }
</style>
