<template>
  <s-table
    ref="sTable"
    :expanded-row-enabled="!!tableContext.expandedGrid"
    :id="tableContext.uniqueId"
    :alert="true"
    :columns="realTableColumns"
    :data="loadData()"
    :rowKey="tableContext.rowKey"
    :showSummary="tableContext.showSummary"
    :rowSelection="tableContext.rowSelection"
    :scroll="{ x: tableContext.scrollXWidth, y: tableContext.scrollYHeight }"
    :showPagination="tableContext.showPagination"
    :hidePagination="tableContext.simpleMode"
    :customPagination="tableContext.customPagination"
    :showSelected="!tableContext.simpleMode"
    :default-page-size="defaultPageSize"
    :pageSizeArray="pageSizeArray"
    :pageMaxSize="tableContext.pageMaxSize"
    :setScrollYHeight="tableContext.setScrollYHeight"
    :selectRowMode="tableContext.selectRowMode"
    :size="tableContext.tableSize"
    :components="components"
    :rowStyleFunction="tableContext.rowStyleFunction"
    @beforeDataChange="beforeDataChange"
    @expand="onExpand"
    @rowClick="handleRowClick"
    @rowDblClick="handleRowDblClick"
    @localDataSourceLengthChange="onStableLocalDataSourceLengthChange"
  >
    <template
      v-for="(item, c_index) in realTableColumns"
      :slot="item.dataIndex"
      slot-scope="text, record, index">
      <template v-if="tableContext.isEditMode && getFromItem(item.dataIndex,text, record, index)">
        <x-form-item
          class="innerTable"
          :style="{ paddingTop: 0, paddingBottom: 0, paddingLeft: 0, paddingRight: 0 }"
          :form="record"
          :attr="getFromItem(item.dataIndex,text, record, index)"
          :service-name="tableContext.serviceName"
          mode="新增/修改"
          :env="tableContext.env"
          :setForm="(obj)=>tableContext.setForm(record,obj)"
          @rowChoose="(row, attr, callback) => tableContext.rowChoose(row, attr, callback, record)"
          @x-form-item-emit-func="(func, attr, value) => handleFormItemEvent(func, attr, value, record, index)"
          :showLabel="false"
          :key="'editRow-' + c_index"
          :row-index="index"
        />
      </template>
      <x-rate
        v-else-if="item.slotType === 'rate'"
        :key="'rate-' + c_index"
        :value="text"
        :disabled="true"
        :allow-half="item.allowHalf"
        :icon="item.rateIcon"
        :max-count="item.maxCount"
        style="zoom:0.9"/>
      <span v-else-if="item.slotType === 'index'" :key="'index-' + c_index">{{ index + 1 }}</span>
      <CustomFuncCel
        :text="text"
        :record="record"
        :index="index"
        :item="item"
        :localDataSource="activeTable?.localDataSource"
        v-else-if="item.slotCustomFunction"
        :key="'customJs-' + c_index"></CustomFuncCel>
      <a
        v-else-if="item.slotType === 'link'"
        :key="'link-' + c_index"
        @click="tableContext.columnClick(item.dataIndex,text,record)">{{ text }}</a>
      <a
        v-else-if="item.slotType === 'gotoUserDetail'"
        :key="'gotoUserDetail-' + c_index"
        @click="tableContext.gotoUserDetail(item.dataIndex,text,record)">{{ text }}</a>
      <span
        v-else-if="isEllipsisFixedColumn(item) && isStableVirtualScrollActive"
        :key="'ellipsis-' + c_index"
        class="x-table-cell-ellipsis-plain">{{ text === '' ? '--' : text }}</span>
      <a-tooltip
        v-else-if="isEllipsisFixedColumn(item) && !isStableVirtualScrollActive"
        :key="'ellipsis-tt-' + c_index"
        placement="topLeft">
        <template slot="title">
          <span>{{ text === '' ? '--' : text }}</span>
        </template>
        {{ text === '' ? '--' : text }}
      </a-tooltip>
      <template v-else-if="item.slotType === 'progress'">
        <!-- websocket-id (配置名称-字段名称-数据行id) -->
        <x-web-socket-progress
          v-if="item.webSocket"
          :key="`progress-${c_index}-${tableContext.requestParameters?.pageNo || 1}-${item.dataIndex}-${record[tableContext.rowKey] || index}`"
          :websocket-id="`${queryParamsName}-${item.dataIndex}-${record[tableContext.rowKey] || index}`"
          :initial-value="text || 0"
          @progress-updated="(data) => handleProgressUpdated(data, record, item.dataIndex)"
        />
        <!-- 表格进度组件 -->
        <a-progress
          v-else
          :key="'progress-' + c_index"
          :percent="text"
          status="active"
          style="padding-right: 20px;"
        />
      </template>
      <template v-else-if="item.slotType === 'badge'">
        <x-badge
          :key="'badge-' + c_index"
          :service-name="tableContext.serviceName"
          :env="tableContext.env"
          v-if="text !== null && text !== undefined"
          :badge-key="item.slotKeyMap"
          :value="text"/>
      </template>
      <span v-else-if="item.slotType === 'date'" :key="'date-' + c_index">{{ format(text, 'yyyy-MM-dd') }}</span>
      <span v-else-if="item.slotType === 'dateTime'" :key="'dateTime-' + c_index">{{ format(text, 'yyyy-MM-dd hh:mm:ss') }}</span>
      <span v-else-if="item.slotType === 'towDecimal'" :key="'towDecimal-' + c_index">{{ numberFormat(text, 2) }}</span>
      <span v-else-if="item.slotType === 'fourDecimal'" :key="'fourDecimal-' + c_index">{{ numberFormat(text, 4) }}</span>
      <span v-else-if="item.slotType === 'int'" :key="'int-' + c_index">{{ numberFormat(text, 0) }}</span>
      <x-image-preview
        v-else-if="item.slotType === 'imgView'"
        :key="'imgView-' + c_index"
        :src="text"
        :size="50"
        shape="square"
      />
      <template v-else-if="item.slotType === 'action'">
        <template v-if="item.actionArr && item.actionArr.length > 0">
          <a-dropdown
            :key="'action-' + c_index"
            :trigger="['click']"
            placement="bottomRight"
            overlayClassName="x-table-action-dropdown"
            :getPopupContainer="getPopupContainer"
          >
            <a class="ant-dropdown-link" @click="e => e.preventDefault()">
              {{ item.scopedSlots?.customRender || item.slotValue }} <a-icon type="down"/>
            </a>
            <a-menu slot="overlay" style="min-width: 60px">
              <template v-if="hasVisibleActionItems(item.actionArr, record, c_index)">
                <a-menu-item
                  v-for="(action_item, actionIndex) in item.actionArr"
                  :key="actionIndex"
                  v-show="!action_item.customFunction || tableContext.customFunctionShow(action_item.customFunction,record,c_index)">
                  <a
                    style="text-align: center"
                    @click="tableContext.action(record, item.dataIndex, action_item.func)"
                  >{{ action_item.text }}</a>
                </a-menu-item>
              </template>
              <a-menu-item v-else disabled>
                <span style="text-align: center; color: #999;">当前环节无操作内容</span>
              </a-menu-item>
            </a-menu>
          </a-dropdown>
        </template>
        <template v-if="!item.actionArr || item.actionArr.length === 0">
          <a :key="'action-' + c_index" @click="tableContext.action(record, item.dataIndex,'action', index)">{{ item.slotValue }}</a>
        </template>
      </template>
    </template>
    <template v-if="tableContext.expandedGrid" slot="expandedRowRender" slot-scope="record">
      <slot
        name="expandedRowRender"
        :selectedRowKeys="tableContext.selectedRowKeys"
        :selectedRows="tableContext.selectedRows"
        :record="record"
      ></slot>
    </template>
    <template slot="footer">
      <slot
        name="footer"
        :selectedRowKeys="tableContext.selectedRowKeys"
        :selectedRows="tableContext.selectedRows"></slot>
    </template>
    <template slot="fixedfooter">
      <slot name="fixedfooter"></slot>
    </template>
  </s-table>
</template>

<script>
import { STable } from '@vue2-client/components'
import { STABLE_VIRTUAL_SCROLL_MIN_ROWS } from '@vue2-client/components/STable/virtualScrollThreshold'
import { formatDate } from '@vue2-client/utils/util'
import XBadge from '@vue2-client/base-client/components/common/XBadge'
import XFormItem from '@vue2-client/base-client/components/common/XForm/XFormItem'
import CustomFuncCel from '@vue2-client/base-client/components/common/XTable/CustomFuncCel.vue'
import { executeStrFunctionByContext } from '@vue2-client/utils/runEvalFunction'
import XRate from '@vue2-client/base-client/components/common/XRate/index.vue'
import XWebSocketProgress from '@vue2-client/base-client/components/common/XWebSocketProgress'
import XImagePreview from '@vue2-client/base-client/components/common/XImagePreview'
import VueDraggableResizable from 'vue-draggable-resizable'
import { mapState } from 'vuex'

export default {
  name: 'XTableWrapper',
  components: {
    STable,
    XBadge,
    XFormItem,
    XRate,
    CustomFuncCel,
    XWebSocketProgress,
    XImagePreview,
    VueDraggableResizable
  },
  data () {
    return {
      isDragging: false, // 添加拖拽状态标记
      // eslint-disable-next-line vue/no-reserved-keys
      _rafId: null, // 添加requestAnimationFrame ID标记
      /** 与 STable.localDataSource 行数同步（见 localDataSourceLengthChange） */
      stableDataSourceLen: 0
    }
  },
  computed: {
    ...mapState('account', { currUser: 'user' }),
    localDataSource () {
      return this.activeTable?.localDataSource
    },
    // 当前包裹的 STable 实例
    activeTable () {
      return this.$refs.sTable
    },
    /**
     * 是否与 STable 内开启纵向虚拟滚动的条件一致（存在 scroll.y 且当前页数据行数大于阈值）
     * 用于省略类列在虚拟滚动时关闭 a-tooltip，减轻大量 Popover 实例带来的开销
     */
    isStableVirtualScrollActive () {
      const y = this.tableContext.scrollYHeight
      const hasScrollY =
        y !== undefined && y !== null && y !== false && y !== ''
      if (!hasScrollY) {
        return false
      }
      return this.stableDataSourceLen > STABLE_VIRTUAL_SCROLL_MIN_ROWS
    },
    realTableColumns () {
      // 1. 先过滤列并设置 ellipsis 属性
      const filteredColumns = this.tableContext.tableColumns
        .filter(item => item.slotType !== 'action' || !this.disableAction)
        .map((item) => {
          // 设置 ellipsis 属性
          if (['ellipsis', 'badge', 'towDecimal', 'date', 'dateTime', 'fourDecimal', 'int', 'customJs'].includes(item.slotType)) {
            item.ellipsis = true
          }
          return item
        })

      // 2. 分组：左固定、普通、右固定
      const leftFixedColumns = []
      const normalColumns = []
      const rightFixedColumns = []

      filteredColumns.forEach(col => {
        if (col.fixed === 'left') {
          leftFixedColumns.push(col)
        } else if (col.fixed === 'right') {
          rightFixedColumns.push(col)
        } else {
          normalColumns.push(col)
        }
      })

      // 3. 按顺序合并：左固定 + 普通 + 右固定
      return [...leftFixedColumns, ...normalColumns, ...rightFixedColumns]
    },
    components () {
      return {
        header: {
          cell: (h, props, children) => {
            const { key, ...restProps } = props
            // 此处的this.realTableColumns 是定义的table的表头属性变量
            const col = this.realTableColumns.find((col) => {
              const k = col.dataIndex || col.key
              return k === key
            })
            if (!col || !col.width || col.slotType === 'action') {
              if (children) {
                return h('th', { ...restProps }, [...children])
              } else {
                return h('th', { ...restProps })
              }
            }

            // 创建一个防止点击排序的容器
            const preventSortProps = {
              style: {
                position: 'absolute',
                right: 0,
                top: 0,
                width: '20px',
                height: '100%',
                zIndex: 10
              },
              on: {
                mousedown: (e) => {
                  e.stopPropagation()
                  e.preventDefault()
                  this.isDragging = true
                }
              }
            }

            const dragProps = {
              key: col.dataIndex || col.key,
              class: 'table-draggable-handle',
              attrs: {
                w: 10,
                x: col.width,
                z: 1,
                axis: 'x',
                draggable: true,
                resizable: false,
              },
              on: {
                dragging: (x, y) => {
                  // 使用requestAnimationFrame优化性能，减少卡顿
                  if (!this._rafId) {
                    this._rafId = requestAnimationFrame(() => {
                      col.width = Math.max(x, 50) // 设置最小列宽为50px
                      this.isDragging = true // 设置拖拽状态
                      this._rafId = null
                    })
                  }
                },
                mousedown: (e) => {
                  // 阻止事件冒泡，防止触发排序
                  e.stopPropagation()
                  e.preventDefault()
                  this.isDragging = true // 设置拖拽状态
                },
                dragstop: () => {
                  // 清除可能存在的动画帧请求
                  if (this._rafId) {
                    cancelAnimationFrame(this._rafId)
                    this._rafId = null
                  }

                  // 拖拽结束时，延迟重置拖拽状态，以防止排序被触发
                  setTimeout(() => {
                    this.isDragging = false
                  }, 100)
                }
              },
              nativeOn: {
                mousedown: (e) => {
                  e.stopPropagation()
                  e.preventDefault()
                  this.isDragging = true // 设置拖拽状态
                }
              }
            }

            const preventSort = h('div', preventSortProps)
            const drag = h('vue-draggable-resizable', { ...dragProps })

            // 修改th的点击事件，在拖拽状态下阻止排序
            const newRestProps = { ...restProps }
            const originalClick = newRestProps.on && newRestProps.on.click
            if (originalClick) {
              newRestProps.on = {
                ...newRestProps.on,
                click: (e) => {
                  if (this.isDragging) {
                    e.stopPropagation()
                    e.preventDefault()
                    return
                  }
                  originalClick(e)
                }
              }
            }

            if (children) {
              return h('th', { ...newRestProps, class: 'resize-table-th' }, [...children, preventSort, drag])
            } else {
              return h('th', { ...newRestProps, class: 'resize-table-th' }, [preventSort, drag])
            }
          },
        }
      }
    }
  },
  props: {
    // 查询配置文件名
    queryParamsName: {
      type: String,
      default: () => {
        return ''
      }
    },
    loadSelectedData: {
      type: Boolean,
      required: false,
      default: false
    },
    disableAction: {
      type: Boolean,
      default: false
    },
    // 默认查询的当页行数
    defaultPageSize: {
      type: Number,
      default: 10
    },
    // 分页配置
    pageSizeArray: {
      type: Array,
      default: () => ['10', '20', '30', '40']
    }
  },
  inject: ['tableContext'],
  methods: {
    /**
     * 检查是否有可见的操作菜单项
     * @param {Array} actionArr 操作数组
     * @param {Object} record 当前行数据
     * @param {Number} c_index 列索引
     * @returns {Boolean} 是否有可见项
     */
    hasVisibleActionItems (actionArr, record, c_index) {
      if (!actionArr || actionArr.length === 0) {
        return false
      }
      return actionArr.some(action_item => {
        return !action_item.customFunction || this.tableContext.customFunctionShow(action_item.customFunction, record, c_index)
      })
    },
    getPopupContainer (triggerNode) {
      // 始终将弹窗渲染到body中，确保层级不受容器限制
      return document.body
    },
    handleRowClick (record) {
      this.$emit('rowClick', record)
    },
    handleRowDblClick (record) {
      this.$emit('rowDblClick', record)
    },
    beforeDataChange (record) {
      this.$emit('beforeDataChange', record)
    },
    onExpand (expanded, record) {
      if (!this.tableContext.expandedGrid) {
        return
      }
      this.$emit('expand', expanded, record)
    },
    onStableLocalDataSourceLengthChange (len) {
      this.stableDataSourceLen = typeof len === 'number' ? len : 0
    },
    /**
     * ellipsis / fixed 列：与列配置 slotType 对齐
     */
    isEllipsisFixedColumn (item) {
      return item && ['ellipsis', 'fixed'].includes(item.slotType)
    },
    setLocalDataSource (data) {
      this.activeTable?.setLocalDataSource(data)
    },
    loadData () {
      if (this.loadSelectedData) {
        return this.loadSelectedDataGen
      } else {
        return this.tableContext.loadData
      }
    },
    loadSelectedDataGen (requestParameters) {
      const { pageNo = 1, pageSize = 10 } = requestParameters || {}
      const startIndex = (pageNo - 1) * pageSize
      const endIndex = startIndex + pageSize
      const paginatedData = this.tableContext.selectedRows.slice(startIndex, endIndex)

      return new Promise((resolve) => {
        resolve({
          data: paginatedData,
          pageNo,
          pageSize,
          totalPage: Math.ceil(this.tableContext.selectedRows.length / pageSize),
          totalCount: this.tableContext.selectedRows.length
        })
      })
    },
    updateSelect (selectedRowKeys, selectedRows) {
      this.activeTable?.updateSelect(selectedRowKeys, selectedRows)
    },
    clearSelected () {
      this.activeTable?.clearSelected()
    },
    refresh (bool) {
      this.activeTable?.refresh(bool)
    },

    /**
     * 格式化日期
     * @param date 日期字符串
     * @param format 格式化方式
     */
    format (date, format) {
      return formatDate(date, format)
    },
    /**
     * 格式化数字
     * @param number string 或者 number
     * @param decimalPlaces 小数位数
     */
    numberFormat (number, decimalPlaces = 2) {
      const value = parseFloat(number)
      if (!isNaN(value)) {
        return value.toFixed(decimalPlaces)
      } else {
        return ''
      }
    },
    getFromItem (model, text, record, index) {
      const aa = this.tableContext.formItems.reduce((acc, item) => {
        if (item.type === 'group') {
          const foundItem = item.groupItems.find(_item => _item.model === model && _item.editRow)
          if (foundItem) {
            acc = foundItem
          }
        } else if (item.model === model && item.editRow) {
          acc = item
        }
        return acc
      }, null)
      if (aa) {
        const tempConfig = JSON.parse(JSON.stringify(aa))
        // 如果找到了字段
        const ColumnIndex = this.realTableColumns.findIndex(item => item.dataIndex === model)
        // 并且表单项是日期框
        if (ColumnIndex !== -1 && ['yearPicker', 'monthPicker', 'datePicker', 'rangePicker'].includes(tempConfig.type)) {
          // 修改他的列宽
          this.realTableColumns[ColumnIndex].width = 220
        }
        // 如果有检验规则检验是数字
        if (ColumnIndex !== -1 && ['number', 'integer', 'float'].includes(tempConfig?.rule?.type)) {
          // 修改他的列宽
          tempConfig.numberInput = true
        }
        if (tempConfig.editRowShowFunc) {
          if (executeStrFunctionByContext(this.tableContext, tempConfig.editRowShowFunc, [text, record, index, tempConfig])) {
            return tempConfig
          }
        } else {
          return tempConfig
        }
      }
      return false
    },
    handleResizeColumn (w, col) {
      col.width = w
    },

    /**
     * 处理进度更新事件
     * @param {Object} data 进度数据
     * @param {Object} record 行数据
     * @param {String} dataIndex 列字段名
     */
    handleProgressUpdated (data, record, dataIndex) {
      // 更新行数据中的进度值
      if (record && dataIndex) {
        this.$set(record, dataIndex, data.value)
      }
      this.$emit('progressUpdated', data, record, dataIndex)
    },
    /**
     * 处理表单项事件，增强事件数据
     * @param {String} func 事件函数名
     * @param {Object} attr 字段配置
     * @param {*} value 字段值
     * @param {Object} record 当前行数据
     * @param {Number} index 当前行索引
     */
    handleFormItemEvent (func, attr, value, record, index) {
      // 获取表格数据源
      const dataSource = this.localDataSource || []

      // 计算下一行的索引和数据
      const nextIndex = index + 1
      const nextRecord = nextIndex < dataSource.length ? dataSource[nextIndex] : null

      // 构建增强的上下文数据
      const enhancedContext = {
        func,
        attr,
        value,
        currentRecord: record,
        currentIndex: index,
        nextRecord,
        nextIndex: nextRecord ? nextIndex : null,
        tableContext: this.tableContext
      }

      // 调用 tableContext 的事件处理方法
      if (this.tableContext && typeof this.tableContext.handleFormItemEvent === 'function') {
        this.tableContext.handleFormItemEvent(enhancedContext)
      }
    }
  }
}
</script>

<style scoped lang="less">
/* 精确修复表头空白问题 */
:deep(.ant-table-fixed-left table, .ant-table-fixed-right table) {
  width: min-content;
}
:deep(.ant-table-fixed-header .ant-table-scroll .ant-table-header) {
  margin-bottom: 0 !important;
  overflow-x: hidden !important;
}
/* 统一表头行高和垂直对齐 */
:deep(.ant-table-thead > tr) {
  height: 54px !important;
  line-height: 54px !important;
}
:deep(.ant-table-thead > tr > th) {
  padding: 0 16px !important;
  vertical-align: middle !important;
  border-bottom: 1px solid #f0f0f0;
}
/* 分页组件不换行 */
:deep(.ant-pagination > li) {
  white-space: nowrap;
}
/* 虚拟滚动下省略列不用 Tooltip 时，在格内做文本截断 */
.x-table-cell-ellipsis-plain {
  display: block;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.innerTable {
  // 行编辑表格输入项样式
  :deep(.ant-form-item) {
    margin: 0;
    .ant-form-item-control-wrapper {
      width: 100%;
    }
    .ant-select {
      width: 100%;
    }
  }
}
</style>
<style>
/* 多操作下拉菜单边框与阴影 */
.x-table-action-dropdown .ant-dropdown-menu {
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
  z-index: 9999;
}

/* vue-draggable-resizable 拖动手柄样式 */
.table-draggable-handle {
  height: 100% !important;
  left: auto !important;
  right: 0;
  cursor: col-resize;
  touch-action: none;
  border: none;
  position: absolute;
  transform: none !important;
  bottom: 0;
  width: 10px !important; /* 减小到10px */
  z-index: 99 !important; /* 提高z-index */
}

/* 拖动手柄的分隔线 */
.table-draggable-handle::after {
  content: "";
  position: absolute;
  top: 50%;
  height: 20px;
  width: 2px;
  background-color: #e8e8e8;
  transition: background-color 0.2s;
  transform: translateY(-50%);
  right: 0;
}

/* 悬停效果 - 只改变颜色 */
.table-draggable-handle:hover::after {
  background-color: #1890ff;
}

/* 拖动时的效果 */
.table-draggable-handle:active::after {
  background-color: #096dd9;
}

/* 表头单元格样式 */
.resize-table-th {
  position: relative;
  overflow: visible !important; /* 确保内容不被裁剪 */
}

/* 表头单元格悬停时的手柄高亮 */
.resize-table-th:hover .table-draggable-handle::after {
  background-color: rgba(24, 144, 255, 0.6);
}
</style>
