<script setup lang="ts">
import Pagination from '@/components/Pagination/index.vue'
import { Setting, Refresh } from '@element-plus/icons-vue'
import { useVModel } from '@vueuse/core'
interface BaseColumn {
  width?: number | string
  minWidth?: number | string
  fixed?: 'left' | 'right' | boolean
  sortable?: boolean | string
  align?: 'left' | 'center' | 'right'
  formatter?: (row: any, column: any, cellValue: any, index: number) => any
  hide?: boolean
  isAction?: boolean
}

interface TypeColumn extends BaseColumn {
  type: 'selection' | 'index' | 'expand'
  label?: string
  prop?: string
}

interface PropColumn extends BaseColumn {
  type?: never
  prop?: string
  label: string
}

type TableColumn = TypeColumn | PropColumn

interface TableCardProps {
  data: any[]
  columns: TableColumn[]
  loading?: boolean
  stripe?: boolean
  border?: boolean
  showPagination?: boolean
  showColumnFilter?: boolean
  pageNo?: number
  pageSize?: number
  total?: number
}

const props = withDefaults(defineProps<TableCardProps>(), {
  data: () => [],
  columns: () => [],
  loading: false,
  stripe: true,
  border: false,
  showPagination: true,
  showColumnFilter: true,
  pageNo: 1,
  pageSize: 10,
  total: 0
})

const emit = defineEmits<{
  (e: 'update:pageNo', value: number): void
  (e: 'update:pageSize', value: number): void
  (e: 'change', pageNo: number, pageSize: number): void
  (e: 'selection-change', selection: any[]): void
  (e: 'sort-change', sortInfo: { prop: string; order: string }): void
}>()

const visibleColumns = ref<string[]>([])

const filterableColumns = computed(() => {
  return props.columns.filter(col => col.prop && !col.type && !col.isAction)
})

const displayColumns = computed(() => {
  return props.columns.filter(col => {
    if (col.type) return true      // selection/index/expand 始终显示
    if (col.isAction) return true  // 操作列始终显示
    if (!col.prop) return false
    return visibleColumns.value.includes(col.prop)
  })
})

function initVisibleColumns() {
  visibleColumns.value = filterableColumns.value
    .filter(col => !col.hide)
    .map(col => col.prop as string)
}

function handleCheckAll(val: boolean | string | number) {
  if (val) {
    visibleColumns.value = filterableColumns.value.map(col => col.prop as string)
  } else {
    visibleColumns.value = []
  }
}

const isAllChecked = computed(() => {
  return filterableColumns.value.length > 0 &&
    visibleColumns.value.length === filterableColumns.value.length
})

const isIndeterminate = computed(() => {
  const len = visibleColumns.value.length
  return len > 0 && len < filterableColumns.value.length
})

const innerPageNo = useVModel(props, 'pageNo', emit, { passive: true })
const innerPageSize = useVModel(props, 'pageSize', emit, { passive: true })

function handlePageChange(pageNo: number, pageSize: number) {
  emit('change', pageNo, pageSize)
}
function handleSelectionChange(selection: any[]) {
  emit('selection-change', selection)
}

function handleSortChange({ prop, order }: { prop: string; order: string | null }) {
  emit('sort-change', { prop, order: order || '' })
}

watch(
  () => props.columns,
  () => { initVisibleColumns() },
  { immediate: true, deep: true }
)
</script>

<template>
  <el-card class="table-card" shadow="never">
    <div class="table-toolbar">
      <div class="toolbar-left">
        <slot name="toolbar-left" />
      </div>
      <div class="toolbar-right">
        <slot name="toolbar-right" />

        <el-popover v-if="showColumnFilter && filterableColumns.length > 0" placement="bottom-end" :width="200"
          trigger="click">
          <template #reference>
            <el-button :icon="Setting" circle />
          </template>

          <div class="column-filter">
            <div class="filter-header">
              <el-checkbox :model-value="isAllChecked" :indeterminate="isIndeterminate" @change="handleCheckAll">
                全部
              </el-checkbox>
              <el-button type="primary" link size="small" :icon="Refresh" @click="initVisibleColumns">
                重置
              </el-button>
            </div>

            <el-checkbox-group v-model="visibleColumns" class="filter-list">
              <el-checkbox v-for="col in filterableColumns" :key="col.prop" :value="col.prop">
                {{ col.label }}
              </el-checkbox>
            </el-checkbox-group>
          </div>
        </el-popover>
      </div>
    </div>

    <el-table :data="data" :stripe="stripe" :border="border" v-loading="loading"
      @selection-change="handleSelectionChange" @sort-change="handleSortChange">
      <template v-for="col in displayColumns" :key="col.prop ?? col.type ?? col.label">
        <el-table-column v-if="col.type" :type="col.type" :width="col.width" :align="col.align ?? 'center'" />
        <el-table-column v-else :prop="col.prop" :label="col.label" :width="col.width" :min-width="col.minWidth"
          :sortable="col.sortable" :align="col.align ?? 'center'"
          :fixed="col.isAction ? (col.fixed ?? 'right') : col.fixed">
          <template #default="scope">
            <slot :name="`column-${col.prop ?? col.label}`" :row="scope.row" :$index="scope.$index">
              {{ col.formatter
                ? col.formatter(scope.row, scope.column, col.prop ? scope.row[String(col.prop)] : undefined, scope.$index)
                : scope.row[String(col.prop)]
              }}
            </slot>
          </template>
        </el-table-column>
      </template>

      <template #empty>
        <slot name="empty">
          <el-empty description="暂无数据" />
        </slot>
      </template>
    </el-table>

    <Pagination v-if="showPagination" v-model:current-page="innerPageNo" v-model:page-size="innerPageSize"
      :total="total" @change="handlePageChange" />

    <slot name="footer" />
  </el-card>
</template>

<style lang="scss" scoped>
.table-card {
  margin-top: 10px;
}

.table-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.toolbar-left,
.toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.column-filter {

  // ✅ 全部 + 重置：左右分布，垂直居中
  .filter-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 8px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--el-border-color-lighter);
  }

  // ✅ 一行一个 checkbox
  .filter-list {
    display: flex;
    flex-direction: column;
    max-height: 300px;
    overflow-y: auto;

    :deep(.el-checkbox) {
      height: 32px;
      margin-right: 0;
    }
  }
}
</style>