<script setup>
import XFormTable from '@vue2-client/base-client/components/common/XFormTable/XFormTable.vue'
import { ref, computed, useAttrs, nextTick, onMounted, onBeforeUnmount } from 'vue'

// 常量配置
const ROW_HEIGHT_DEFAULT = '37px'
const BOOLEAN_STYLE_KEYS = [
  'button-row-0margin',
  'top-hidden',
  'dialog-style',
  'button-style',
  'header-center',
  'expanded-grid-white',
  'report-mode',
  'listview-hide-selected',
  'min-height-auto'
]
const ALLOWED_PAGINATION_STYLES = ['pagination-center', 'custom-pagination']
const SYNC_DELAY_AFTER_PAGE = 80
const SYNC_DELAY_RETRY = 60
const SYNC_DELAY_EXPAND = 20

// 选择器常量
const FIXED_TABLE_SELECTORS = [
  '.ant-table-fixed-right .ant-table-tbody > tr',
  '.ant-table-fixed-right .ant-table-body-inner > table > tbody > tr',
  '.ant-table-fixed-right .ant-table-body > table > tbody > tr'
]
const MAIN_TBODY_SELECTORS = ['.ant-table-body > table > tbody', '.ant-table-tbody']
// 仅主表滚动区域 tbody（不含左右固定列表格），用于按 data-row-key 对齐展开行与固定列
const MAIN_SCROLL_TBODY_SELECTORS = [
  '.ant-table-scroll .ant-table-body > table > tbody',
  '.ant-table-body > table > tbody'
]
const FIXED_TBODY_SELECTORS = [
  '.ant-table-fixed-right .ant-table-body-inner > table > tbody',
  '.ant-table-fixed-right .ant-table-body > table > tbody',
  '.ant-table-fixed-right .ant-table-tbody'
]
const TABLE_BODY_SELECTORS = ['.ant-table-body', '.ant-table-body-inner']

// 辅助函数
const getRowKey = (tr) => tr?.getAttribute?.('data-row-key') || tr?.dataset?.rowKey || ''

const escapeRowKeyAttr = (key) => {
  const s = String(key)
  if (typeof CSS !== 'undefined' && typeof CSS.escape === 'function') return CSS.escape(s)
  return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"')
}

const cleanRowStyles = (element, isCollapse = false) => {
  if (!element) return
  element.removeAttribute('data-synced-height')
  if (isCollapse) {
    element.style.setProperty('height', '0', 'important')
    element.style.setProperty('min-height', '0', 'important')
    element.style.setProperty('max-height', '0', 'important')
    element.style.setProperty('line-height', '0', 'important')
    element.style.setProperty('overflow', 'hidden', 'important')
  } else {
    element.style.removeProperty('height')
    element.style.removeProperty('min-height')
    element.style.removeProperty('max-height')
    element.style.removeProperty('line-height')
  }
}

const cleanCellStyles = (td, isCollapse = false) => {
  if (isCollapse) {
    td.style.setProperty('height', '0', 'important')
    td.style.setProperty('min-height', '0', 'important')
    td.style.setProperty('max-height', '0', 'important')
    td.style.setProperty('line-height', '0', 'important')
    td.style.setProperty('padding', '0', 'important')
    td.style.setProperty('border', 'none', 'important')
    td.style.setProperty('overflow', 'hidden', 'important')
  } else {
    td.style.removeProperty('height')
    td.style.removeProperty('min-height')
    td.style.removeProperty('max-height')
    td.style.removeProperty('line-height')
    td.style.removeProperty('vertical-align')
  }
}

const queryFirst = (container, selectors) => {
  for (const sel of selectors) {
    const el = container.querySelector(sel)
    if (el) return el
  }
  return null
}

const props = defineProps({
  tableStyle: {
    type: String,
    default: 'formtable-col1'
  }
})

const attrs = useAttrs()

const wrapperClassObject = computed(() => {
  const classes = {}

  for (const key of BOOLEAN_STYLE_KEYS) {
    const val = attrs[key]
    const truthy = val === true || val === '' || val === 'true'
    if (truthy) classes[`h-form-table-${key}`] = true
  }

  const paginationAttr = attrs?.paginationStyle
  if (paginationAttr && ALLOWED_PAGINATION_STYLES.includes(paginationAttr)) {
    classes[`h-form-table-${paginationAttr}`] = true
  }
  return classes
})

const wrapperStyleObject = computed(() => {
  const rowHeight = attrs['row-height'] || attrs.rowHeight || ROW_HEIGHT_DEFAULT
  const tableMinHeight = attrs['table-min-height'] || attrs.tableMinHeight || null
  // 表格高度偏移量（分页器+边距等固定部分），配置600显示550，偏移50
  const tableMinHeightOffset = 50
  return {
    '--row-height': rowHeight,
    '--table-min-height': tableMinHeight ? `calc(${tableMinHeight} - ${tableMinHeightOffset}px)` : undefined
  }
})

const xFormTableRef = ref()
const wrapperRef = ref()

// 状态变量
let observer = null
let resizeObserver = null
let isSyncing = false
let rafId = 0
let syncAfterPageChangeTimer = 0
// 记录上一次同步时的固定行高度快照，防止 MutationObserver 循环触发
let lastSyncedSnapshot = ''

const getWrapperEl = () => wrapperRef.value

const scheduleSync = () => {
  if (isSyncing) return
  if (rafId) cancelAnimationFrame(rafId)
  rafId = requestAnimationFrame(() => {
    rafId = 0
    syncFixedExpandedHeights()
  })
}
const scheduleSyncAfterPageChange = () => {
  if (syncAfterPageChangeTimer) clearTimeout(syncAfterPageChangeTimer)
  syncAfterPageChangeTimer = setTimeout(() => {
    syncAfterPageChangeTimer = 0
    scheduleSync()
    setTimeout(scheduleSync, SYNC_DELAY_RETRY)
  }, SYNC_DELAY_AFTER_PAGE)
}

const setupHeightSync = () => {
  try {
    const wrapper = getWrapperEl()
    if (!wrapper || observer) return

    const mainTable = queryFirst(wrapper, MAIN_TBODY_SELECTORS)
    const fixedTbody = queryFirst(wrapper, FIXED_TBODY_SELECTORS)
    const tableBody = queryFirst(wrapper, TABLE_BODY_SELECTORS)

    const observerOptions = {
      childList: true,
      subtree: true
    }

    observer = new MutationObserver((mutations) => {
      if (isSyncing) return
      const wrapper = getWrapperEl()
      if (wrapper && wrapper.dataset.heightSyncing) return

      const hasChildList = mutations.some(m => m.type === 'childList')
      if (hasChildList) {
        scheduleSyncAfterPageChange()
      }
    })

    if (mainTable) observer.observe(mainTable, observerOptions)
    if (fixedTbody) observer.observe(fixedTbody, observerOptions)

    if (!resizeObserver && tableBody && typeof ResizeObserver !== 'undefined') {
      resizeObserver = new ResizeObserver(() => scheduleSync())
      resizeObserver.observe(tableBody)
    }
  } catch (e) {
    console.warn('[HFormTable] setupHeightSync error:', e)
  }
}

const syncFixedExpandedHeights = () => {
  try {
    const wrapper = getWrapperEl()
    if (!wrapper) return
    if (isSyncing) return
    isSyncing = true

    const mainScrollTbody = queryFirst(wrapper, MAIN_SCROLL_TBODY_SELECTORS)
    if (!mainScrollTbody) {
      isSyncing = false
      return
    }

    const fixedRows = Array.from(wrapper.querySelectorAll(FIXED_TABLE_SELECTORS.join(', ')))

    // 生成当前快照：如果与上次完全相同，跳过写入
    const snapshotParts = []
    fixedRows.forEach(f => {
      const key = getRowKey(f)
      if (!key) return
      let mainTr = null
      try {
        mainTr = mainScrollTbody.querySelector(`tr[data-row-key="${escapeRowKeyAttr(key)}"]`)
      } catch (e) { mainTr = null }
      if (!mainTr) return
      const h = Math.round(mainTr.getBoundingClientRect().height)
      if (h) snapshotParts.push(key + ':' + h)
    })
    const snapshot = snapshotParts.join('|')
    if (snapshot === lastSyncedSnapshot) {
      isSyncing = false
      return
    }
    lastSyncedSnapshot = snapshot

    fixedRows.forEach(f => {
      const key = getRowKey(f)
      if (!key) return

      let mainTr = null
      try {
        mainTr = mainScrollTbody.querySelector(`tr[data-row-key="${escapeRowKeyAttr(key)}"]`)
      } catch (e) { mainTr = null }

      if (!mainTr) {
        if (f.dataset.syncedHeight) {
          cleanRowStyles(f, true)
          f.querySelectorAll('td').forEach(td => cleanCellStyles(td, true))
        }
        return
      }

      const h = Math.round(mainTr.getBoundingClientRect().height)
      if (!h) return

      const hs = String(h)
      if (f.dataset.syncedHeight === hs) return
      f.dataset.syncedHeight = hs

      f.style.cssText = ''
      f.style.setProperty('height', h + 'px', 'important')
      f.style.setProperty('min-height', h + 'px', 'important')
      f.style.setProperty('max-height', h + 'px', 'important')
      f.style.setProperty('line-height', 'normal', 'important')

      f.querySelectorAll('td').forEach(td => {
        td.style.cssText = ''
        td.style.setProperty('height', h + 'px', 'important')
        td.style.setProperty('min-height', h + 'px', 'important')
        td.style.setProperty('max-height', h + 'px', 'important')
        td.style.setProperty('line-height', 'normal', 'important')
        td.style.setProperty('vertical-align', 'middle', 'important')
      })
    })
  } catch (e) {
    console.warn('[HFormTable] syncFixedExpandedHeights error:', e)
  } finally {
    isSyncing = false
  }
}

const onExpandLog = () => {
  nextTick(() => {
    if (!observer) {
      setupHeightSync()
    }
    syncFixedExpandedHeights()
    setTimeout(() => syncFixedExpandedHeights(), SYNC_DELAY_EXPAND)
  })
}

onMounted(() => {
  nextTick(() => {
    setupHeightSync()
    syncFixedExpandedHeights()
  })
})

onBeforeUnmount(() => {
  try {
    observer?.disconnect?.()
    resizeObserver?.disconnect?.()
    if (rafId) cancelAnimationFrame(rafId)
    if (syncAfterPageChangeTimer) clearTimeout(syncAfterPageChangeTimer)
  } finally {
    observer = null
    resizeObserver = null
    rafId = 0
    syncAfterPageChangeTimer = 0
    isSyncing = false
  }
})

// 计算属性
const isCustomPagination = computed(() => {
  const paginationAttr = attrs?.paginationStyle || ''
  return props.tableStyle === 'custom-pagination' || paginationAttr === 'custom-pagination'
})

const isHiddenFunctionalArea = computed(() => {
  return attrs?.hiddenFunctionalArea === 'true' || attrs?.hiddenFunctionalArea === true
})

const computedDefaultPageSize = computed(() => {
  const pageMaxSize = attrs?.pageMaxSize
  const numericPageSize = pageMaxSize ? Number(pageMaxSize) : null
  return (numericPageSize && numericPageSize > 0) ? numericPageSize : 10
})

defineExpose({
  getXFormTableInstance: () => xFormTableRef.value,
  waitConfigEnd: () => xFormTableRef.value?.waitConfigEnd?.() ?? Promise.resolve()
})
</script>

<template>
  <div
    ref="wrapperRef"
    class="h-form-table-wrapper"
    :class="[
      `h-form-table-${tableStyle}`,
      wrapperClassObject
    ]"
    :style="wrapperStyleObject"
  >
    <x-form-table
      ref="xFormTableRef"
      v-bind="$attrs"
      :defaultPageSize="computedDefaultPageSize"
      :customPagination="isCustomPagination"
      :hiddenFunctionalArea="isHiddenFunctionalArea"
      @expand="onExpandLog"
      @configEnd="$emit('configEnd')"
      v-on="$listeners"
    >
      <template v-for="(_, name) in $slots" #[name]="slotData">
        <slot :name="name" v-bind="slotData" />
      </template>
    </x-form-table>
  </div>
</template>

<style scoped lang="less">
// 表格行高度变量，默认37px
@row-height: var(--row-height, 37px);

.h-form-table-wrapper {
  // 基础样式
  :deep(.table-wrapper) {
    .ant-table {
      .ant-table-row {
        margin: 0 !important;
        height: @row-height !important;
        max-height: @row-height !important;
        line-height: @row-height !important;

        > td {
          height: @row-height !important;
          min-height: @row-height !important;
          max-height: @row-height !important;
          padding: 0 8px !important;
          box-sizing: border-box !important;
          vertical-align: middle !important;

          // 去掉内部元素的 margin，防止带下拉框的行被撑高
          .ant-form-item,
          .ant-form-item-control {
            margin-bottom: 0 !important;
            margin-top: 0 !important;
          }
          .ant-select,
          .ant-input,
          .ant-picker {
            margin-bottom: 0 !important;
            margin-top: 0 !important;
            height: @row-height !important;
            max-height: @row-height !important;
            line-height: @row-height !important;
          }
          .ant-select-selection--single {
            height: calc(@row-height - 2px) !important;
            min-height: calc(@row-height - 2px) !important;
          }
          .ant-select-selection__rendered {
            line-height: calc(@row-height - 2px) !important;
          }
        }
      }
      font-size: 16px;
    }

    .ant-alert-info {
      display: none;
    }
  }

  :deep(.ant-card) {
    margin: -10px 0px 29px 0px;
  }
  :deep(.ant-space .ant-btn .anticon) {
    display: none;
  }
  :deep(.ant-space .ant-btn) {
    border: 0px;
    box-shadow: none;
    padding: 0px;
    color: #5D5C5C;
    font-weight: bold;
    letter-spacing: 0em;
    font-size: 18px;
    line-height: normal;
    background-color: transparent;
    font-family: "Source Han Sans";
  }

  :deep(.ant-card-body) {
    padding: 0 6px;
  }

  :deep(.ant-table-small) {
    border-width: 0;

    .ant-table-fixed {
      border-radius: 0;
      border-bottom: 1px solid #f0f0f0;
    }
  }

  // 操作列（固定列）高度与主体一致，行内文字垂直居中
  :deep(.ant-table-fixed-right .ant-table-body-inner) {
    table tbody tr.ant-table-row {
      height: @row-height !important;
      max-height: @row-height !important;

      > td {
        height: @row-height !important;
        min-height: @row-height !important;
        max-height: @row-height !important;
        padding: 0 8px !important;
        box-sizing: border-box !important;
        vertical-align: middle !important;
        line-height: @row-height !important;
      }
    }
  }
  // 主表行高与固定列一致
  :deep(.table-wrapper .ant-table-body > table > tbody > tr.ant-table-row) {
    height: @row-height !important;
    max-height: @row-height !important;
  }

  :deep(.ant-table-fixed-right .ant-btn),
  :deep(.ant-table-fixed-right a) {
    line-height: inherit !important;
    vertical-align: middle !important;
    padding: 0 4px;
  }

  // 表格高度样式
  &.h-form-table-height {
    :deep(.table-wrapper) {
      .ant-select-open ~ .ant-table-content {
        height: 500px !important;
      }
    }
  }
  // 表格最小高度自动
  &.h-form-table-min-height-auto {
    :deep(.table-wrapper) {
      .ant-table:not(.ant-table-empty) {
        .ant-table-content {
          min-height: auto !important;
          .ant-table-body {
            min-height: auto !important;
          }
        }
      }
    }
  }

  // 自定义表格固定高度（通过 table-min-height 属性设置）
  // 只在表格有数据时应用
  :deep(.table-wrapper) {
    .ant-table:not(.ant-table-empty) {
      .ant-table-content {
        .ant-table-body {
          min-height: calc(var(--table-min-height, 300px) - 50px);
        }
      }
    }
  }

  // 表格样式
  &.h-form-table-table {
    :deep(.ant-table-small .ant-table-fixed-header) {
      .ant-table-content {
        .ant-table-content {
          .ant-table-body {
            border-radius: 0 0 4px 4px;
            // 修复展开行后固定列与主体错位：保持表体滚动容器为自动滚动
            overflow: auto !important;
          }
        }
      }
    }
  }
  // 移除之前隐藏固定列占位行的样式，保持与主体行数一致
  // 展开行单元格去除额外内边距，避免高度不一致
  :deep(.ant-table-expanded-row > td) {
    padding: 0 !important;
  }
  // 展开内容中的表单/控件去掉外边距，避免撑高
  :deep(.ant-table-expanded-row .ant-form-item) {
    margin-bottom: 0 !important;
  }

  // 移除之前的隐藏固定列样式，避免展开/合并后操作列消失
  &.h-form-table-dialog-style {
    /* 选择前面的兄弟元素 */
    :global(.ant-col.ant-col-24[name="trGroup"]:has(+ .ant-card .ant-card-body .h-form-table-wrapper.h-form-table-dialog-style)) {
      padding-top: 0px !important;
      padding-left: 0px !important;
    }

    :global(.ant-card-body:has(.h-form-table-wrapper.h-form-table-dialog-style)) {
      padding-top: 0px !important;
      padding-left: 0px !important;
    }
  }
  // 隐藏按钮区域
  &.h-form-table-button-area-hide {
    :deep(.ant-btn) {
      display: none;
    }

    :deep(.table-wrapper) {
      margin-top: -39px;
    }
  }

  // 顶部区域隐藏（与按钮隐藏一致的视觉需求）
  &.h-form-table-top-hidden {
    :deep(.ant-btn) {
      display: none;
    }

    :deep(.table-wrapper) {
      margin-top: -39px;
    }
  }

  // 列样式1
  &.h-form-table-formtable-col1 {
    :deep(.table-wrapper) {
      .ant-row {
        .ant-col span {
          border: none;
          width: auto;
          margin-bottom: auto;
        }
      }

      .ant-table {
        .ant-table-body {
          .ant-table-fixed colgroup col:nth-child(2) {
            width: 50px;
            min-width: 50px;
          }
        }

        .ant-table-header {
          .ant-table-fixed colgroup col:nth-child(2) {
            width: 50px;
            min-width: 50px;
          }
        }
      }
    }
  }

  // 底部分页居中 & 自定义分页样式（共用样式）
  &.h-form-table-bottom-center,
  &.h-form-table-custom-pagination {
    :deep(.table-wrapper) {
      .ant-row-flex-start {
        position: relative;
        display: flex;
        align-items: center;
        margin-top: 12px !important;
        height: 32px;

        // 防止第一个子元素无限拉伸，影响分页居中
        > :first-child {
          flex: 0 0 auto;
        }

        // 将第二个子元素（分页）绝对居中
        > :nth-child(2) {
          position: absolute;
          left: 50%;
          transform: translateX(-50%);
        }
      }
    }
  }

  // 按钮行0margin
  &.h-form-table-button-row-0margin {
    :deep(.ant-row) {
      margin: 0px;
    }
  }
  // crud按钮样式
  &.h-form-table-button-style {
    :deep(.ant-btn){
      border-radius: 6px;
      background-color: #FFFFFF;
      border: 1px solid #9499A0;
      color: #313131;
      font-weight: normal;
      letter-spacing: 0em;
      font-size: 16px;
      font-family: "Source Han Sans";
      line-height: normal;
    }
  }
  // 表格内容全部居中样式
  &.h-form-table-header-center {
    :deep(.ant-table-thead > tr > th),
    :deep(.ant-table-tbody > tr > td) {
      text-align: center !important;
    }
  }
  // 行展开白色背景
  &.h-form-table-expanded-grid-white {
    :deep(.ant-table-expanded-row){
      background-color: white;
    }
  }
  // listView模式下隐藏"已选择"按钮（该按钮包含 monitor 图标）
  &.h-form-table-listview-hide-selected {
    :deep(.ant-badge:has(.ant-btn .anticon-monitor)) {
      display: none !important;
    }
  }
  // 报表样式
  @skip-cells: 2;
  &.h-form-table-report-mode {
    --skip-cells: 4;
    :deep(.ant-table-header){
      padding-bottom: 0px !important;
    }
    :deep(.ant-table-content){
      border: 1px solid #E5E9F0;
    }
    :deep(.resize-table-th){
      background-color: white !important;
    }
    :deep(.ant-table-row) {
      .ant-table-row-cell-ellipsis {
        &:nth-child(n + @{skip-cells}) {
          color: #3362DA !important;
        }
      }
    }
  }
}
</style>
<!-- 非scoped样式：全局覆盖表格内下拉框宽度 -->
<style lang="less">
.h-form-table-wrapper {
  // 只针对普通数据行的单元格，排除展开行
  .ant-table-tbody > tr:not(.ant-table-expanded-row) > td {
    --form-label-width: 0 !important;

    .ant-select,
    .ant-select-selection {
      width: 100% !important;
    }
    .ant-form-item {
      width: 100% !important;
    }
    .ant-form-item-control-wrapper {
      width: 100% !important;
      flex: none !important;
    }
    .ant-select-selection__rendered {
      width: 100% !important;
    }
  }
}
</style>
