<script lang="ts" setup generic="T">
import type { TableInstance, TableProps } from 'element-plus'
import { FilterPayload, SortField, SortOrder, TableContextKey } from './token'

interface Props extends /* @vue-ignore */ Partial<Omit<TableProps<T>, 'data'>> {
  data: T[]
  loading: boolean
  handleQuery?: (payload?: FilterPayload) => void
  sortingFields?: SortField[]
  sortFn?: (prop: string, order: SortOrder | null) => void
  customClass?: boolean
  showBorder?: boolean
}

const props = defineProps<Props>()

const emits = defineEmits<{
  'update:sortingFields': [fields: SortField[]]
}>()

const attrs = useAttrs()
const tableRef = ref<TableInstance>()

const defaultOptions: Partial<Props> = {
  size: 'default',
  stripe: true,
  border: true,
  highlightCurrentRow: true,
  showOverflowTooltip: true,
  scrollbarAlwaysOn: true,
  showBorder: false,
  customClass: false,
  tooltipOptions: {
    popperClass: 'max-w-120'
  }
}

const bindProps = computed(() => {
  const { data, sortingFields, ...otherProps } = props

  return {
    ...defaultOptions,
    ...attrs,
    ...otherProps,
    data: data || []
  }
})

const handleDefaultSort = (prop: string, order: SortOrder | null) => {
  const newFields = [...(props.sortingFields || [])]

  const idx = newFields.findIndex((f) => f.field === prop)

  if (order === null) {
    if (idx > -1) {
      newFields.splice(idx, 1)
    }
  } else {
    if (idx > -1) {
      newFields[idx] = { ...newFields[idx], order }
    } else {
      newFields.push({ field: prop, order })
    }
  }

  emits('update:sortingFields', newFields)
  props.handleQuery?.()
}

const safeSortingFields = computed(() => props.sortingFields || [])
const safeData = computed(() => props.data || [])
const safeLoading = computed(() => props.loading)

provide(TableContextKey, {
  onQuery: (payload) => props.handleQuery?.(payload),
  onSort: (prop, order) => {
    if (props.sortFn) {
      props.sortFn(prop, order)
    } else {
      handleDefaultSort(prop, order)
    }
  },
  // 关键：传递响应式的 data 和 sortingFields
  data: safeData,
  sortingFields: safeSortingFields,
  loading: safeLoading
})

defineExpose({
  elTableRef: tableRef
})
</script>

<template>
  <el-table
    ref="tableRef"
    v-loading="loading"
    :class="{ 'zm-table': !customClass, 'show-border': showBorder }"
    v-bind="bindProps"
    :data="data"
  >
    <template v-for="(_, name) in $slots" #[name]="slotData">
      <slot :name="name" v-bind="slotData || {}"></slot>
    </template>
  </el-table>
</template>

<style>
.zm-table {
  border-radius: 8px;

  &::before,
  &::after {
    display: none;
  }

  .el-table__inner-wrapper {
    &::before,
    &::after {
      display: none;
    }
  }

  .el-table__border-left-patch {
    display: none;
  }

  .el-table__cell {
    height: 52px;

    &:last-child {
      border-right: none !important;
    }
  }

  .el-table__header {
    border-bottom-right-radius: 8px;
    border-bottom-left-radius: 8px;

    .el-table__cell {
      background: var(--el-fill-color-light) !important;

      &:last-child {
        .cell {
          border-right: none;
        }
      }
    }

    tr:first-child {
      .el-table__cell {
        &:first-child {
          border-bottom-left-radius: 8px;
        }

        &:last-child {
          border-bottom-right-radius: 8px;
        }
      }
    }
  }

  .el-table__body-wrapper {
    .el-table__cell {
      &:last-child {
        border-top-right-radius: 8px;
        border-bottom-right-radius: 8px;
      }

      &:first-child {
        border-bottom-left-radius: 8px;
        border-top-left-radius: 8px;
      }
    }
  }
}

.zm-table:not(.show-border) {
  .el-table__cell {
    border: none !important;
  }

  .el-table__header {
    .el-table__cell {
      .cell {
        border-right: var(--el-table-border);
        border-color: var(--el-table-header-text-color);
      }

      &:last-child {
        .cell {
          border-right: none;
        }
      }
    }
  }

  .el-table__row {
    &:last-child {
      .el-table__cell {
        border-bottom: none;
      }
    }
  }
}
</style>
