<template>
  <div class="tree-table">
    <div class="table-scroll-container" v-if="!loading">
      <!-- 表头 -->
      <div class="table-header">
        <div
          v-for="col in columns"
          :key="col.key"
          :class="['table-cell', col.class || '']"
          :style="col.style"
        >
          {{ col.title }}
        </div>
      </div>

      <!-- 表格内容 -->
      <div class="table-body">
        <div
          v-for="item in flattenData"
          :key="item[rowKey]"
          class="table-row"
        >
          <div
            v-for="col in columns"
            :key="col.key"
            :class="['table-cell', col.class || '']"
            :style="getCellStyle(item, col)"
            @click="handleCellClick(item, col)"
          >
            <!-- 组织架构列（树形展示） -->
            <template v-if="col.treeColumn">
              <template v-if="item.loading">
                <div class="icon-wrapper">
                  <template v-if="item[levelKey] >= 1">
                    <svg class="svg-loading" viewBox="0 0 24 24" width="14" height="14">
                      <circle cx="12" cy="12" r="10" fill="none" stroke="#e0e0e0" stroke-width="2"/>
                      <path fill="none" stroke="#ff5f16" stroke-width="2" d="M12 2a10 10 0 0 1 10 10">
                        <animateTransform
                          attributeName="transform"
                          type="rotate"
                          from="0 12 12"
                          to="360 12 12"
                          dur="1s"
                          repeatCount="indefinite"
                        />
                      </path>
                    </svg>
                  </template>
                  <van-icon v-else name="loading" size="14" class="loading-icon" />
                </div>
              </template>
              <template v-else-if="item[hasChildrenKey] || (item[childrenKey] && item[childrenKey].length > 0)">
                <div class="icon-wrapper" @click.stop="toggleExpand(item)">
                  <van-icon
                    :name="item.expanded ? 'arrow-down' : 'arrow'"
                    size="12"
                    class="expand-icon"
                  />
                </div>
              </template>
              <template v-else>
                <div class="icon-wrapper empty-icon"></div>
              </template>
              <span class="org-name">{{ item[col.dataIndex] }}</span>
            </template>
            <!-- 普通列 -->
            <template v-else>
              <slot
                :name="col.key"
                :record="item"
                :value="item[col.dataIndex]"
                :column="col"
              >
                {{ formatValue(item[col.dataIndex], col) }}
              </slot>
            </template>
          </div>
        </div>
      </div>
    </div>
    <!-- Loading 遮罩 -->
    <div v-else class="table-loading">
      <van-loading type="spinner" color="#ff5f16" size="24" />
      <span class="loading-text">加载中...</span>
    </div>
  </div>
</template>

<script>
export default {
  name: 'TreeTable',
  props: {
    // 表格列配置
    columns: {
      type: Array,
      default: () => []
    },
    // 表格数据（树形结构）
    data: {
      type: Array,
      default: () => []
    },
    // 每行的唯一标识字段
    rowKey: {
      type: String,
      default: 'id'
    },
    // 子节点字段名
    childrenKey: {
      type: String,
      default: 'children'
    },
    // 层级字段名
    levelKey: {
      type: String,
      default: 'level'
    },
    // 是否有子节点字段名
    hasChildrenKey: {
      type: String,
      default: 'hasChildren'
    },
    // 缩进大小（像素）
    indentSize: {
      type: Number,
      default: 16
    },
    // 基础内边距（像素）
    basePadding: {
      type: Number,
      default: 16
    },
    // 表格loading状态
    loading: {
      type: Boolean,
      default: false
    },
    // 是否横屏模式
    isLandscape: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      internalData: [],
      // 用于触发 flattenData 重新计算
      updateTrigger: 0
    }
  },
  computed: {
    // 根据展开状态计算显示的数据
    flattenData() {
      // 依赖 updateTrigger 确保数据变化时重新计算
      this.updateTrigger
      return this.flattenTree(this.internalData)
    }
  },
  watch: {
    data: {
      handler(newData) {
        this.internalData = this.initTreeData(JSON.parse(JSON.stringify(newData)))
      },
      immediate: true,
      deep: true
    },
    // 监听横屏模式变化，动态调整表格CSS变量
    isLandscape(val) {
      this.updateTableStyle(val)
    }
  },
  mounted() {
    // 初始化时根据横屏状态设置样式
    this.updateTableStyle(this.isLandscape)
  },
  beforeDestroy() {
    // 组件销毁前清理样式
    this.updateTableStyle(false)
  },
  methods: {
    // 初始化树形数据，确保 loading 属性存在
    initTreeData(nodes) {
      for (const node of nodes) {
        if (node.loading === undefined) {
          this.$set(node, 'loading', false)
        }
        if (node[this.childrenKey] && node[this.childrenKey].length > 0) {
          this.initTreeData(node[this.childrenKey])
        }
      }
      return nodes
    },
    // 递归扁平化树形数据
    flattenTree(nodes, result = []) {
      for (const node of nodes) {
        result.push(node)
        if (node.expanded && node[this.childrenKey] && node[this.childrenKey].length > 0) {
          this.flattenTree(node[this.childrenKey], result)
        }
      }
      return result
    },
    // 获取单元格样式
    getCellStyle(item, col) {
      const style = { ...(col.style || {}) }
      // 如果是树形列，添加缩进
      if (col.treeColumn) {
        style.paddingLeft = `${(this.basePadding + item[this.levelKey] * this.indentSize) / 50}rem`
      }
      return style
    },
    // 格式化值
    formatValue(value, col) {
      if (col.formatter && typeof col.formatter === 'function') {
        return col.formatter(value)
      }
      return value
    },
    // 切换展开/收起
    async toggleExpand(item) {
      // 如果已经在加载中，忽略点击
      if (item.loading) return

      // 如果子节点未加载过，先异步加载
      if (item[this.hasChildrenKey] && (!item[this.childrenKey] || item[this.childrenKey].length === 0)) {
        this.$set(item, 'loading', true)

        // 使用箭头函数确保 this 上下文正确
        const onLoaded = (children) => {
          this.$set(item, 'loading', false)
          if (children && children.length > 0) {
            // 初始化子节点的 loading 属性
            const initializedChildren = this.initTreeData(children)
            this.$set(item, this.childrenKey, initializedChildren)
            this.$set(item, 'expanded', true)
            // 强制触发更新
            this.forceUpdateInternalData()
            this.$emit('expand', item)
          }
        }

        this.$emit('load-children', item, onLoaded)
      } else {
        // 已加载过，直接切换展开状态
        this.$set(item, 'expanded', !item.expanded)
        // 强制触发更新
        this.forceUpdateInternalData()
        if (item.expanded) {
          this.$emit('expand', item)
        } else {
          this.$emit('collapse', item)
        }
      }
    },
    // 强制更新 internalData，触发 flattenData 重新计算
    forceUpdateInternalData() {
      // 增加计数器触发 computed 重新计算
      this.updateTrigger++
    },
    // 更新表格样式（横屏/竖屏切换）
    updateTableStyle(isLandscape) {
      const el = this.$el
      if (!el) return

      if (isLandscape) {
        // 横屏时使用固定像素值
        el.style.setProperty('--table-row-height', '36px')
        el.style.setProperty('--table-font-size', '13px')
        el.style.setProperty('--table-font-size-body', '14px')
      } else {
        // 竖屏时移除CSS变量，使用rem默认值
        el.style.removeProperty('--table-row-height')
        el.style.removeProperty('--table-font-size')
        el.style.removeProperty('--table-font-size-body')
      }
    },
    // 处理单元格点击
    handleCellClick(item, col) {
      if (col.clickable !== false) {
        this.$emit('cellClick', item, col)
      }
    },
    // 展开所有
    expandAll() {
      const expandNodes = (nodes) => {
        for (const node of nodes) {
          this.$set(node, 'expanded', true)
          if (node[this.childrenKey] && node[this.childrenKey].length > 0) {
            expandNodes(node[this.childrenKey])
          }
        }
      }
      expandNodes(this.internalData)
      // 强制触发更新
      this.forceUpdateInternalData()
    },
    // 收起所有
    collapseAll() {
      const collapseNodes = (nodes) => {
        for (const node of nodes) {
          this.$set(node, 'expanded', false)
          if (node[this.childrenKey] && node[this.childrenKey].length > 0) {
            collapseNodes(node[this.childrenKey])
          }
        }
      }
      collapseNodes(this.internalData)
      // 强制触发更新
      this.forceUpdateInternalData()
    }
  }
}
</script>

<style lang="less" scoped>
@primary-color: #ff5f16;
@bg-gray: #f5f5f5;
@text-primary: #333;
@text-secondary: #666;
@text-light: #999;
@border-color: #e8e8e8;

.tree-table {
  background-color: #fff;
  overflow: hidden;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.table-loading {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 200px;

  .loading-text {
    margin-top: 8px;
    font-size: 14px;
    color: #999;
  }
}

.table-scroll-container {
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  flex: 1;
  min-height: 0;
}

// 表头
.table-header {
  display: flex;
  padding: 0;
  border-top: (1/50rem) solid @border-color;
  border-bottom: (1/50rem) solid @border-color;
  background-color: #fafafa;
  min-width: max-content;
  position: sticky;
  top: 0;
  z-index: 20;
  height: var(--table-row-height, (40/50rem));

  .table-cell {
    font-size: var(--table-font-size, (13/50rem));
    color: @text-secondary;
    font-weight: 500;
    padding: 0;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    white-space: nowrap;
    border-right: (1/50rem) solid @border-color;
    height: var(--table-row-height, (40/50rem));

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

    &.col-org {
      width: (130/50rem);
      min-width: (130/50rem);
      max-width: (130/50rem);
      position: sticky;
      left: 0;
      background-color: #fafafa;
      z-index: 21;
      justify-content: flex-start;
      text-align: left;
      padding: 0 0 0 (16/50rem);
      box-shadow: 2px 0 6px -2px rgba(0, 0, 0, 0.1);
      border-left: (1/50rem) solid @border-color;
    }

    &.col-num {
      width: (85/50rem);
      min-width: (85/50rem);
    }

    &.col-percent {
      width: (100/50rem);
      min-width: (100/50rem);
    }
  }
}

// 表格内容
.table-body {
  min-width: max-content;

  .table-row {
    display: flex;
    border-bottom: (1/50rem) solid @border-color;
    transition: background-color 0.2s;
    align-items: center;
    height: var(--table-row-height, (40/50rem));

    &:active {
      background-color: #f5f5f5;
    }

    .table-cell {
      padding: 0;
      box-sizing: border-box;
      border-right: (1/50rem) solid @border-color;
      height: var(--table-row-height, (40/50rem));

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

      &.col-org {
        width: (130/50rem);
        min-width: (130/50rem);
        max-width: (130/50rem);
        display: flex;
        align-items: center;
        font-size: var(--table-font-size-body, (14/50rem));
        color: @text-primary;
        position: sticky;
        left: 0;
        background-color: #fff;
        z-index: 10;
        border-right: (1/50rem) solid @border-color;
        border-left: (1/50rem) solid @border-color;
        justify-content: flex-start;
        box-shadow: 2px 0 6px -2px rgba(0, 0, 0, 0.1);

        .icon-wrapper {
          display: flex;
          align-items: center;
          justify-content: center;
          width: (20/50rem);
          height: (20/50rem);
          flex-shrink: 0;
          cursor: pointer;

          &.empty-icon {
            cursor: default;
          }
        }

        .expand-icon {
          color: @text-light;
        }

        .loading-icon {
          color: @primary-color;
          animation: rotate 1s linear infinite;
          font-weight: bold;
        }

        .svg-loading {
          display: block;
        }

        @keyframes rotate {
          from {
            transform: rotate(0deg);
          }
          to {
            transform: rotate(360deg);
          }
        }

        .org-name {
          flex: 1;
          margin-left: (4/50rem);
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
          min-width: 0;
        }
      }

      &.col-num {
        width: (85/50rem);
        min-width: (85/50rem);
        text-align: center;
        font-size: var(--table-font-size-body, (14/50rem));
        color: @text-primary;
        display: flex;
        align-items: center;
        justify-content: center;

        &.highlight {
          color: @primary-color;
        }

        &.highlight-blue {
          color: #5B8FF9;
        }
      }

      &.col-percent {
        width: (100/50rem);
        min-width: (100/50rem);
        text-align: center;
        font-size: var(--table-font-size-body, (14/50rem));
        color: @text-primary;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    }
  }
}
</style>
