<!-- 表格组件，带分页（默认分页大于一页时显示） -->
<template>
  <div
    class="art-table"
    :class="{ 'header-background': showHeaderBackground }"
    :style="{
      marginTop: marginTop + 'px',
      height: total ? 'calc(100% - 90px)' : 'calc(100% - 25px)'
    }"
  >
    <div class="table-container">
      <el-table
        ref="tableRef"
        v-loading="loading"
        :data="tableData"
        :row-key="rowKey"
        :row-class-name="rowClassName"
        :height="height"
        :max-height="maxHeight"
        :show-header="showHeader"
        :highlight-current-row="highlightCurrentRow"
        :size="tableSizeComputed"
        :stripe="stripeComputed"
        :border="borderComputed"
        :tree-props="treeProps"
        :default-expand-all="defaultExpandAll"
        :header-cell-style="{
          backgroundColor: showHeaderBackground ? 'var(--el-fill-color-lighter)' : '',
          fontWeight: '500'
        }"
        @row-click="handleRowClick"
        @row-contextmenu="handleRowContextmenu"
        @selection-change="handleSelectionChange"
        @cell-mouse-enter="handleCellMouseEnter"
        @cell-mouse-leave="handleCellMouseLeave"
      >
        <!-- 序号列 -->
        <el-table-column
          v-if="index && tableData.length > 0"
          type="index"
          width="60"
          label="序号"
          align="center"
          fixed="left"
        />

        <!-- 动态列 -->
        <slot v-if="tableData.length"></slot>

        <!-- 操作列固定在右侧 -->
        <el-table-column
          v-if="actions && tableData.length > 0"
          label="操作"
          :width="actionsWidth"
          fixed="right"
          align="left"
        >
          <template #default="{ row }">
            <div class="table-actions">
              <component :is="renderActions(row)" />
            </div>
          </template>
        </el-table-column>

        <!-- 空数据 -->
        <template #empty>
          <el-empty :description="emptyText" v-show="!loading" />
        </template>
      </el-table>
    </div>

    <!-- 分页 -->
    <div
      v-if="pagination && tableData.length > 0"
      class="table-pagination"
      :class="paginationAlign"
    >
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="pageSizes"
        :pager-count="isMobile ? 5 : 7"
        :total="total"
        :background="true"
        :size="paginationSize"
        :layout="paginationLayoutComputed"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :hide-on-single-page="hideOnSinglePage"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
  import { h } from 'vue'
  import { ElDropdown, ElDropdownMenu, ElDropdownItem } from 'element-plus'

  import { useTableStore } from '@/store/modules/table'
  const { width } = useWindowSize()
  const isMobile = computed(() => width.value < 500)

  interface TableAction {
    label: string
    handler: (row: any) => void
    type?: 'primary' | 'danger'
    permission?: string
  }

  interface TableProps {
    /** 表格数据源 */
    data?: any[]
    /** 是否显示加载状态 */
    loading?: boolean
    /** 行数据的 Key，用于标识每一行数据 */
    rowKey?: string
    /** 行的 className 的回调方法 */
    rowClassName?: ((data: { row: any; rowIndex: number }) => string) | string
    /** 是否显示边框 */
    border?: boolean | null
    /** 是否使用斑马纹样式 */
    stripe?: boolean | null
    /** 是否显示序号列 */
    index?: boolean
    /** 表格高度，可以是数字或 CSS 值 */
    height?: string | number
    /** 表格最大高度，可以是数字或 CSS 值 */
    maxHeight?: string | number
    /** 是否显示表头 */
    showHeader?: boolean
    /** 是否高亮当前行 */
    highlightCurrentRow?: boolean
    /** 空数据时显示的文本 */
    emptyText?: string
    /** 是否显示分页 */
    pagination?: boolean
    /** 总条目数 */
    total?: number
    /** 当前页码 */
    currentPage?: number
    /** 每页显示条目个数 */
    pageSize?: number
    /** 每页显示个数选择器的选项列表 */
    pageSizes?: number[]
    /** 只有一页时是否隐藏分页器 */
    hideOnSinglePage?: boolean
    /** 分页器的对齐方式 */
    paginationAlign?: 'left' | 'center' | 'right'
    /** 分页器的大小 */
    paginationSize?: 'small' | 'default' | 'large'
    /** 分页器的布局 */
    paginationLayout?: string
    /** 是否显示表头背景色 */
    showHeaderBackground?: boolean | null
    /** 表格距离顶部距离 */
    marginTop?: number
    /** 表格大小 */
    size?: 'small' | 'default' | 'large'
    /** 树形表格配置 */
    treeProps?: { children?: string; hasChildren?: string }
    /** 是否默认展开所有行 */
    defaultExpandAll?: boolean
    /** 操作列配置 */
    actions?: ((row: any) => TableAction[]) | null
    /** 操作列宽度 */
    actionsWidth?: number
    /** 直接显示的操作按钮数量，默认2个 */
    inlineActionsCount?: number
  }

  const props = withDefaults(defineProps<TableProps>(), {
    data: () => [],
    loading: false,
    rowKey: 'id',
    rowClassName: undefined,
    border: null,
    stripe: null,
    index: false,
    height: '100%',
    showHeader: true,
    highlightCurrentRow: false,
    emptyText: '暂无数据',
    pagination: true,
    total: 0,
    currentPage: 1,
    pageSize: 20,
    hideOnSinglePage: false,
    pageSizes: () => [10, 20, 30, 50],
    paginationAlign: 'center',
    paginationSize: 'default',
    paginationLayout: '',
    showHeaderBackground: null,
    marginTop: 20,
    treeProps: undefined,
    defaultExpandAll: false,
    actions: null,
    actionsWidth: 140,
    inlineActionsCount: 1
  })

  /*
   * 计算分页布局
   * 移动端跟pc端使用两种不同的布局
   */
  const paginationLayoutComputed = computed(() => {
    if (props.paginationLayout) {
      return props.paginationLayout
    }
    return isMobile.value
      ? 'prev, pager, next, jumper, sizes, total'
      : 'total, sizes, prev, pager, next, jumper'
  })

  const emit = defineEmits([
    'update:currentPage',
    'update:pageSize',
    'row-click',
    'row-contextmenu',
    'size-change',
    'current-change',
    'selection-change',
    'cell-mouse-enter',
    'cell-mouse-leave'
  ])

  const tableStore = useTableStore()
  const { tableSize } = storeToRefs(tableStore)

  // 表格实例
  const tableRef = ref()

  // 提供给父组件的方法
  defineExpose({
    // 展开所有行
    expandAll: () => {
      const elTable = tableRef.value
      if (!elTable) return

      // 递归处理树形数据
      const processRows = (rows: any[]) => {
        rows.forEach((row) => {
          const hasChildren = row.children?.length > 0
          if (hasChildren) {
            elTable.toggleRowExpansion(row, true)
            processRows(row.children)
          }
        })
      }

      processRows(props.data)
    },

    // 收起所有行
    collapseAll: () => {
      const elTable = tableRef.value
      if (!elTable) return

      // 递归处理树形数据
      const processRows = (rows: any[]) => {
        rows.forEach((row) => {
          const hasChildren = row.children?.length > 0
          if (hasChildren) {
            elTable.toggleRowExpansion(row, false)
            processRows(row.children)
          }
        })
      }

      processRows(props.data)
    }
  })

  // 表格大小 - props优先级高于store
  const tableSizeComputed = computed(() => {
    return props.size || tableSize.value
  })

  // 斑马纹
  const stripeComputed = computed(() => {
    return props.stripe === null ? tableStore.isZebra : props.stripe
  })

  // 边框
  const borderComputed = computed(() => {
    return props.border === null ? tableStore.isBorder : props.border
  })

  // 表头背景
  const showHeaderBackground = computed(() => {
    return props.showHeaderBackground === null
      ? tableStore.isHeaderBackground
      : props.showHeaderBackground
  })

  // 表格数据
  const tableData = computed(() => {
    // 如果不显示分页或使用后端分页，直接返回原始数据
    if (!props.pagination || props.total > props.data.length) return props.data
    const start = (props.currentPage - 1) * props.pageSize
    const end = start + props.pageSize
    return props.data.slice(start, end)
  })

  // 当前页
  const currentPage = computed({
    get: () => props.currentPage,
    set: (val) => emit('update:currentPage', val)
  })

  // 每页条数
  const pageSize = computed({
    get: () => props.pageSize,
    set: (val) => emit('update:pageSize', val)
  })

  // 行点击事件
  const handleRowClick = (row: any, column: any, event: any) => {
    emit('row-click', row, column, event)
  }

  // 行右键事件
  const handleRowContextmenu = (row: any, column: any, event: any) => {
    emit('row-contextmenu', row, column, event)
  }

  // 单元格鼠标进入事件
  const handleCellMouseEnter = (row: any, column: any, cell: any, event: any) => {
    emit('cell-mouse-enter', row, column, cell, event)
  }

  // 单元格鼠标离开事件
  const handleCellMouseLeave = (row: any, column: any, cell: any, event: any) => {
    emit('cell-mouse-leave', row, column, cell, event)
  }

  // 选择变化事件
  const handleSelectionChange = (selection: any) => {
    emit('selection-change', selection)
  }

  // 每页条数改变
  const handleSizeChange = (val: number) => {
    emit('size-change', val)
  }

  // 当前页改变
  const handleCurrentChange = (val: number) => {
    emit('current-change', val)

    scrollToTop()
  }

  // 表格滚动到顶部
  const scrollToTop = () => {
    nextTick(() => {
      if (tableRef.value) {
        tableRef.value.setScrollTop(0)
      }
    })
  }

  // 渲染操作列
  const renderActions = (row: any) => {
    if (!props.actions) return null

    const actionList = props.actions(row)

    // 如果没有操作按钮,显示提示
    if (actionList.length === 0) {
      return h(
        'span',
        { style: 'color: var(--el-text-color-placeholder); font-size: 12px;' },
        '暂无可用操作'
      )
    }

    // 如果操作数量 <= inlineActionsCount，直接显示所有文本
    if (actionList.length <= props.inlineActionsCount) {
      return h(
        'div',
        { style: 'display: flex; gap: 20px;' },
        actionList.map((action) =>
          h(
            'span',
            {
              style: `color: ${action.type === 'danger' ? 'var(--el-color-danger)' : 'var(--el-color-primary)'}; cursor: pointer;`,
              onClick: () => action.handler(row)
            },
            action.label
          )
        )
      )
    }

    // 如果操作数量 > inlineActionsCount，显示前 inlineActionsCount 个 + 更多下拉菜单
    const inlineActions = actionList.slice(0, props.inlineActionsCount)
    const moreActions = actionList.slice(props.inlineActionsCount)

    return h('div', { style: 'display: flex; gap: 20px; align-items: center;' }, [
      ...inlineActions.map((action) =>
        h(
          'span',
          {
            style: `color: ${action.type === 'danger' ? 'var(--el-color-danger)' : 'var(--el-color-primary)'}; cursor: pointer;`,
            onClick: () => action.handler(row)
          },
          action.label
        )
      ),
      h(
        ElDropdown,
        {
          onCommand: (handler: (row: any) => void) => handler(row)
        },
        {
          default: () =>
            h(
              'span',
              {
                style:
                  'display: flex; align-items: center; cursor: pointer; color: var(--el-color-warning);'
              },
              [h('span', '更多')]
            ),
          dropdown: () =>
            h(ElDropdownMenu, {}, () =>
              moreActions.map((action) =>
                h(
                  ElDropdownItem,
                  {
                    command: () => action.handler(row),
                    style: action.type === 'danger' ? 'color: var(--el-color-danger);' : ''
                  },
                  () => action.label
                )
              )
            )
        }
      )
    ])
  }
</script>

<style lang="scss" scoped>
  .art-table {
    .table-container {
      height: 100%;
    }

    .table-pagination {
      display: flex;
      margin-top: 16px;

      // 分页对齐方式
      &.left {
        justify-content: flex-start;
      }

      &.center {
        justify-content: center;
      }

      &.right {
        justify-content: flex-end;
      }
    }

    :deep(.el-table) {
      th.el-table__cell {
        font-weight: 600;
      }
    }

    &.header-background {
      :deep(.el-table) {
        th.el-table__cell {
          background-color: var(--el-fill-color-light);
        }
      }
    }

    // 解决el-image 和 el-table冲突层级冲突问题
    // 只对包含图片的单元格应用，避免影响 fixed 列
    ::v-deep(.el-table__cell:has(.el-image)) {
      position: static !important;
    }

    // 确保固定列能正常工作
    :deep(.el-table__fixed-right) {
      right: 0 !important;
    }
  }

  // 移动端分页
  @media (max-width: $device-phone) {
    :deep(.el-pagination) {
      display: flex;
      flex-wrap: wrap;
      gap: 15px 0;
      align-items: center;
      justify-content: center;

      .el-pagination__sizes {
        .el-select {
          width: 100px !important;

          .el-select__wrapper {
            height: 30px !important;
          }
        }
      }

      .el-pager {
        li {
          margin-right: 2px;
        }
      }

      .el-pagination__jump {
        margin-left: 5px;

        .el-input {
          height: 32px !important;
        }
      }
    }
  }
</style>
