<template>
  <div class="table-pro-content">
    <div class="card padding" v-if="props.searchFormOptions">
      <FormProMax
          ref="searchFormRef"
          :form-item-options="props.searchFormOptions"
          v-model:value="searchParams"
          v-bind="props.searchFormProps"
      >
        <template v-slot:formOperation>
          <a-space class="margin-right flex-end">
            <a-button type="primary" @click="search">
              <search-outlined/>
              搜索
            </a-button>
            <a-button danger @click="resetFormAndTable">
              <rollback-outlined/>
              重置
            </a-button>
          </a-space>
        </template>
      </FormProMax>
    </div>
    <div class="card padding margin-top-xs">
      <div class="flex-justify-between">
        <slot name="tableHeader" :selectKeys="selectKeys" :selectRows="selectRows"></slot>
        <div></div>
        <slot name="tableHeaderRight" :selectKeys="selectKeys" :selectRows="selectRows"></slot>
        <a-space>
          <template v-if="!props.searchFormOptions">
            <a-tooltip>
              <template #title>刷新数据</template>
              <a-button shape="circle" @click="requestGetTableData">
                <ReloadOutlined/>
              </a-button>
            </a-tooltip>
          </template>
          <template v-if="props.isPrinter">
            <a-tooltip>
              <template #title>打印数据</template>
              <a-button shape="circle">
                <PrinterOutlined/>
              </a-button>
            </a-tooltip>
          </template>
        </a-space>
      </div>
      <a-table
          class="margin-top"
          v-bind="props"
          :columns="tableColumns"
          :row-selection="props.isSelection ? props.selectionProps ? props.selectionProps : defaultSelectProps : null"
          :data-source="dataSource"
          :loading="loading"
          :pagination="false"
      >
        <template v-for="(_,key) in slots" v-slot:[key]="scope">
          <slot v-if="!includes(['tableHeader','tableHeaderRight'],key)" :name="key" v-bind="scope"></slot>
        </template>
      </a-table>
      <a-pagination
          v-if="props.isPagination"
          class="flex-end margin-top margin-right"
          v-model:current="pageParams.current"
          v-model:page-size="pageParams.size"
          :total="pageParams.total"
          v-bind="props.paginationProps"
          @change="handleCurrentChange"
          @showSizeChange="handleSizeChange"
      />
    </div>
  </div>
</template>

<script
    setup
    lang="ts"
    generic="T extends BaseTableRowRecord = {},P extends { [key: string]: any } ={}"
>
import FormProMax from "@/components/form/FormProMax.vue";
import {PrinterOutlined, ReloadOutlined, RollbackOutlined, SearchOutlined} from "@ant-design/icons-vue";
import {computed, onMounted, Ref, ref} from "vue";
import {FormInstance} from "ant-design-vue";
import useTableProMax from "@/hooks/useTableProMax";
import {includes, isEmpty} from "lodash-es";
import {BaseTableRowRecord, TableProMaxProps, TableProMaxRowSelect, TableProMaxSlots} from "@/types/components/table";

const selectKeys = ref<string[]>([])
const selectRows = ref<T[]>([]) as Ref<T[]>

const defaultSelectProps: TableProMaxRowSelect<T> = {
  type: "checkbox",
  selectedRowKeys: selectKeys as any,
  preserveSelectedRowKeys: true,
  onSelect: (record, selected) => {
    if (selected) {
      selectKeys.value.push(record[props.rowKey] as string)
      selectRows.value.push(record)
    } else {
      selectKeys.value.splice(selectKeys.value.findIndex(x => x === record[props.rowKey]));
      selectRows.value.splice(selectRows.value.findIndex(r => r[props.rowKey] === record[props.rowKey]))
    }
  },
  onChange: (selectedRowKeys, selectedRows) => {
    selectKeys.value = selectedRowKeys as string[];
    selectRows.value = selectedRows;
  },
}

const clearSelect = () => {
  selectKeys.value = [];
  selectRows.value = [];
}

const props = withDefaults(defineProps<TableProMaxProps<T, P>>(), {
  needIndex: true,
  searchFormProps: () => {
    return {
      grid: {
        xs: 24,
        sm: 12,
        md: 8,
        lg: 6,
        xl: 4
      },
      labelCol: undefined,
      wrapperCol: undefined
    }
  },
  rowKey: 'snowFlakeId',
  requestAuto: true,
  isPagination: true,
  isSelection: false,
  paginationProps: () => {
    return {
      showTotal: (total) => `共 ${total} 条`,
      showSizeChanger: true,
    }
  },
  bordered: true,
  showSorterTooltip: undefined,
  showHeader: undefined,
  expandFixed: undefined,
  expandRowByClick: undefined,
  defaultExpandAllRows: undefined,
  showExpandColumn: undefined,
  sticky: undefined
})
const slots = defineSlots<TableProMaxSlots<T>>()

const tableColumns = computed(() => {
  let cols = props.columns;
  if (!isEmpty(cols) && props.needIndex) {
    if (!(cols?.[0].dataIndex === 'index')) {
      cols?.unshift({
        dataIndex: 'index',
        width: 80,
        title: '序号',
        customRender: ({index}) => index + 1
      })
    }
  }
  return cols;
})

/**
 * 表单实例
 */
const searchFormRef = ref<FormInstance>() as Ref<FormInstance>
/**
 * 查询参数
 */
const searchParams = ref<P | Record<string, any>>(props.defaultSearchParams || {}) as Ref<P>

const {
  loading,
  dataSource,
  pageParams,
  search,
  requestGetTableData,
  handleSizeChange,
  handleCurrentChange,
  resetState
} = useTableProMax(props.requestApi,
    searchFormRef,
    searchParams,
    props.isPagination,
    props.dataCallback,
    props.requestError
)

onMounted(() => props.requestAuto && requestGetTableData(true))

/**
 * 重置表单并查询
 */
const resetFormAndTable = () => {
  searchFormRef.value?.resetFields()
  requestGetTableData()
}

defineExpose({
  selectKeys,
  selectRows,
  requestGetTableData,
  clearSelect,
  resetTable: () => {
    searchFormRef.value?.resetFields()
    resetState();
  }
})

</script>

<style scoped lang="scss">
.card {
  box-sizing: border-box;
  background-color: #ffffff;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  box-shadow: 0 0 12px rgba(0, 0, 0, 0.05);
}
</style>
