<template>
  <div v-loading="loading" class="pro-table">
    <div class="header">
      <div class="action-container">
        <el-button
          v-if="props.createText"
          type="primary"
          size="mini"
          :icon="Plus"
          @click="onCreate"
        >
          {{ props.createText }}
        </el-button>
      </div>
    </div>
    <el-table :data="displayTableData" v-bind="$attrs">
      <slot></slot>
    </el-table>
    <el-config-provider :locale="zhCn">
      <el-pagination
        v-if="paginationInfo.showPagination"
        class="pagination"
        :current-page="paginationInfo.currentPage"
        layout="total, jumper, prev, pager, next, sizes"
        :page-size="paginationInfo.pageSize"
        :total="paginationInfo.total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      >
      </el-pagination>
    </el-config-provider>
  </div>
</template>

<script setup lang="ts">
import { defineProps, withDefaults, provide, ref } from 'vue'

import zhCn from 'element-plus/lib/locale/lang/zh-cn'
import { Plus } from '@element-plus/icons-vue'

import {
  ITableDataItem,
  IPaginationInfo,
  IOnCreated,
} from '~/interfaces/proTable'
import {
  DELETE_ROW,
  UPDATE_ROW,
  PAGINATION_INFO,
  CREATE_ROW,
} from '~/constants/proTable'
import { HandleProTableData } from '~/tools/proTable'

interface Props {
  request: () => Promise<{ data: ITableDataItem[] }>
  // 分页
  showPagination?: boolean
  currentPage?: number
  pageSize?: number
  pageSizes?: number[]
  // header
  createText?: string
}
const props = withDefaults(defineProps<Props>(), {
  currentPage: 1,
  pageSize: 10,
  pageSizes: () => [10, 20, 30, 40, 50, 100],
  showPagination: true,
})

const emit = defineEmits(['onCreated'])

// 分页
const paginationInfo = ref<IPaginationInfo>({
  currentPage: props.currentPage,
  pageSize: props.pageSize,
  pageSizes: props.pageSizes,
  showPagination: props.showPagination,
  total: 0,
})
const handleSizeChange = (val: number) => {
  paginationInfo.value.pageSize = val
  updateTheView()
}
const handleCurrentChange = (val: number) => {
  paginationInfo.value.currentPage = val
  updateTheView()
}
// 数据获取
const tableData = ref<ITableDataItem[]>([])
const displayTableData = ref<ITableDataItem[]>(tableData.value)
const loading = ref(false)
async function getData() {
  try {
    loading.value = true
    const { data } = await props.request()
    tableData.value = data
    paginationInfo.value.total = tableData.value?.length
    updateTheView()
    loading.value = false
  } catch (e) {
    loading.value = false
    console.log((e as Error).message)
  }
}
onMounted(async () => {
  await getData()
})

const updateTheView = () => {
  if (!paginationInfo.value?.showPagination) {
    displayTableData.value = tableData.value
  }
  const { currentPage, pageSize } = paginationInfo.value
  const pageStart: number = (currentPage - 1) * pageSize
  displayTableData.value = tableData.value.slice(
    pageStart,
    pageStart + pageSize,
  )
  paginationInfo.value.total = tableData.value.length
}

const handleTable = computed(() => {
  return new HandleProTableData(updateTheView, tableData)
})

const onCreate = () => {
  emit('onCreated', handleTable.value.createRow)
}

// 暴漏给给父组件用的方法
defineExpose({
  paginationInfo,
  ...handleTable.value,
})

// 发送给后代组件使用
provide(PAGINATION_INFO, paginationInfo)
provide(UPDATE_ROW, handleTable.value.updatedRow)
provide(DELETE_ROW, handleTable.value.deleteRow)
provide(CREATE_ROW, handleTable.value.createRow)
</script>

<style scoped lang="scss">
.pro-table {
  width: 100%;

  .header {
    margin-bottom: 8px;
  }

  .pagination {
    display: flex;
    justify-content: flex-end;
    margin-top: 15px;
    $marginLeft: 15px;

    ::v-deep(.btn-prev) {
      margin-left: $marginLeft !important;
    }

    ::v-deep(.el-input) {
      margin-left: $marginLeft !important;
    }

    ::v-deep(.el-pager li) {
      margin: 0 2px;
    }
  }
}
</style>
