<template>
  <div class="table-view">
    <ElTable
      ref="tableRef"
      :data="paginatedData"
      border
      :stripe="stripe"
      header-align="center"
      height="100%"
      v-bind="attrs"
      :class="internalIsMore ? 'is-more-active' : ''"
      @header-click="handleTableHeaderClick"
    >
      <ElTableColumn
        v-if="selectionable"
        type="selection"
        width="40"
        fixed="left"
        header-align="center"
        align="center"
      >
      </ElTableColumn>
      <ElTableColumn
        v-if="serialNumberable"
        label="序号"
        type="index"
        width="55"
        fixed="left"
        header-align="center"
        align="center"
        :class="isMore ? 'is-more-active' : ''"
      ></ElTableColumn>
      <template v-for="column in columns" :key="column.key">
        <ElTableColumn
          v-if="column.type === 'expand'"
          v-bind="column"
          header-align="center"
        >
          <!-- 当type等于expand时， 配置通过h函数渲染、txs语法或者插槽自定义内容 -->
          <template #default="scope">
            <div>
              <component
                :is="column.render"
                v-if="column.render"
                :row="scope.row"
                :index="scope.$index"
              />
              <slot
                v-else-if="column.slot"
                name="expand"
                :row="scope.row"
                :index="scope.$index"
              ></slot>
            </div>
          </template>
        </ElTableColumn>
        <RenderColumn v-else :col="column">
          <template v-for="(_, name) of slots" #[name]="scope">
            <slot :name="name" v-bind="scope" />
          </template>
        </RenderColumn>
      </template>
    </ElTable>
  </div>
</template>
<script setup lang="tsx" generic="T">
import {
  type Slot,
  useAttrs,
  useSlots,
  type PropType,
  shallowRef,
  ref,
  nextTick,
} from 'vue'
import type { CustomColumn } from '@/types/table'
import RenderColumn from './RenderColumn.vue'
import { ElTable } from 'element-plus'
import type { TableInstance } from 'element-plus'

const tableRef = shallowRef<TableInstance>()
const internalIsMore = ref(false)
const selectionHeaderClickCount = ref(0)

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const props = defineProps({
  paginatedData: {
    type: Array,
    required: true,
  },
  columns: {
    type: Array as PropType<CustomColumn<T>>,
    required: true,
  },
  stripe: {
    type: Boolean,
    default: false,
  },
  serialNumberable: {
    type: Boolean,
    default: false,
  },
  selectionable: {
    type: Boolean,
    default: false,
  },
  isMore: {
    type: Boolean,
    default: false,
  },
})

const attrs = useAttrs()
const slots = useSlots() as Record<string, Slot>

const setCurrentRow = (row: T) => {
  tableRef.value?.setCurrentRow(row)
}

const toggleRowSelection = (row: T, selected: boolean = true) => {
  tableRef.value?.toggleRowSelection(row, selected)
}

const clearSelection = () => {
  tableRef.value?.clearSelection()
}
const toggleAllSelection = () => {
  tableRef.value?.toggleAllSelection()
}

const handleTableHeaderClick = (column: { type?: string }, event: Event) => {
  if (column.type === 'selection' && props.isMore) {
    event.preventDefault()
    event.stopPropagation()

    selectionHeaderClickCount.value++
    const count = selectionHeaderClickCount.value

    const actions = {
      1: () => selectAllRows(true),
      2: () => selectAllRows(true, true),
      3: () => selectAllRows(false, false),
    }

    if (actions[count as keyof typeof actions]) {
      actions[count as keyof typeof actions]()
    }
  }
}

const selectAllRows = (select: boolean, setInternalIsMore?: boolean) => {
  nextTick(() => {
    if (tableRef.value && props.paginatedData.length > 0) {
      props.paginatedData.forEach((row) => {
        tableRef.value?.toggleRowSelection(row, select)
      })
    }

    if (setInternalIsMore !== undefined) {
      internalIsMore.value = setInternalIsMore
    }

    if (!select && setInternalIsMore === false) {
      selectionHeaderClickCount.value = 0
    }
  })
}

defineExpose({
  tableRef,
  setCurrentRow,
  toggleRowSelection,
  clearSelection,
  toggleAllSelection,
  internalIsMore,
})
</script>

<style lang="scss" scoped>
.table-view {
  height: 100%;
  overflow: hidden;
  position: relative;
}

::v-deep .is-more-active {
  .el-table__header .el-table-column--selection .cell {
    height: auto !important;
    padding: 0px 0 !important;
    overflow: visible !important;

    .el-checkbox {
      position: relative;
      transform: translateY(-7px);

      &::after {
        content: 'All';
        color: #262626;
        font-size: 12px;
        position: absolute;
        top: 100%;
        left: 50%;
        transform: translateX(-50%);
        line-height: 1;
        white-space: nowrap;
      }
    }
  }
}
</style>
