<script lang="ts">
const transformPortSpeed = (portInfo: NdmSwitchPortInfo, type: 'in' | 'out' | 'total'): string => {
  const units = ['B/s', 'KB/s', 'MB/s', 'GB/s', 'TB/s'];
  const { inBytes, lastInBytes, outBytes, lastOutBytes, inFlow, outFlow, flow } = portInfo;
  let result: number = 0;
  if (inFlow && outFlow && flow) {
    if (type === 'in') {
      result = inFlow;
    }
    if (type === 'out') {
      result = outFlow;
    }
    if (type === 'total') {
      result = flow;
    }
  } else {
    let dInBytes = 0;
    let dOutBytes = 0;
    if (inBytes < lastInBytes) {
      dInBytes = inBytes + JAVA_UNSIGNED_INTEGER_MAX_VALUE - lastInBytes;
    } else {
      dInBytes = inBytes - lastInBytes;
    }
    if (outBytes < lastOutBytes) {
      dOutBytes = outBytes + JAVA_UNSIGNED_INTEGER_MAX_VALUE - lastOutBytes;
    } else {
      dOutBytes = outBytes - lastOutBytes;
    }
    if (type === 'in') {
      result = dInBytes;
    }
    if (type === 'out') {
      result = dOutBytes;
    }
    if (type === 'total') {
      result = dInBytes + dOutBytes;
    }
    result /= NDM_SWITCH_PROBE_INTERVAL;
  }
  let index = 0;
  while (result >= 1024 && index < units.length - 1) {
    result /= 1024;
    index++;
  }
  return `${result.toFixed(3)} ${units[index]}`;
};
</script>

<script setup lang="ts">
/**
 * 交换机端口布局组件
 *
 * 功能描述：
 * 1. 解析端口名称格式（x/y/z），按槽位（x/y）进行分组
 * 2. 实现两行纵向优先的Grid布局显示端口
 * 3. 提供端口状态的可视化指示（在线/离线/未知）
 * 4. 通过悬停弹窗显示端口详细信息和速率数据
 *
 * 技术特点：
 * - 基于 Vue 3 Composition API
 * - 使用 NaiveUI 组件库
 * - 支持亮色/暗色主题切换
 * - 响应式数据处理和布局
 */

// 类型定义导入
import type { NdmSwitchPortInfo } from '@/apis/domains';

// 常量导入
import { JAVA_UNSIGNED_INTEGER_MAX_VALUE, NDM_SWITCH_PROBE_INTERVAL } from '@/constants';

// NaiveUI 组件导入
import { NCard, NGrid, NGridItem, NPopover } from 'naive-ui';

// Vue 3 响应式 API
import { computed, toRefs } from 'vue';

/**
 * 组件属性定义
 *
 * @param portInfoList 端口信息列表
 * 数据格式：NdmSwitchPortInfo[]
 * 每个端口包含：portName, upDown, inFlow, outFlow, inBytes, outBytes 等字段
 *
 * 端口名称格式："x/y/z"
 * - x: 槽位号
 * - y: 子卡号
 * - z: 接口序号
 *
 * 示例数据：
 * [
 *   { portName: "1/0/1", upDown: 1, inFlow: 1024, outFlow: 2048, ... },
 *   { portName: "1/0/2", upDown: 0, inFlow: 0, outFlow: 0, ... },
 *   { portName: "2/0/1", upDown: 2, inFlow: 512, outFlow: 1024, ... }
 * ]
 */
const props = defineProps<{
  portInfoList: NdmSwitchPortInfo[];
}>();

const { portInfoList } = toRefs(props);

/**
 * 解析端口名称并按槽位分组
 *
 * 示例输入数据：
 * portInfoList = [
 *   { portName: "1/0/3", upDown: 1, ... },
 *   { portName: "1/0/1", upDown: 0, ... },
 *   { portName: "2/0/2", upDown: 1, ... },
 *   { portName: "1/1/1", upDown: 2, ... },
 *   { portName: "2/0/1", upDown: 1, ... }
 * ]
 */
const groupedPorts = computed(() => {
  // 第一步：创建分组容器
  // 使用 Map 数据结构存储分组结果，key 为槽位标识，value 为端口数组
  const groups = new Map<string, NdmSwitchPortInfo[]>();

  // 第二步：遍历所有端口，按槽位进行分组
  portInfoList.value.forEach((port) => {
    // 解析端口名称格式 "x/y/z" -> ["x", "y", "z"]
    // 例如："1/0/3" -> ["1", "0", "3"]
    const parts = port.portName.split('/');

    if (parts.length >= 3) {
      // 组合槽位键：槽位号/子卡号 (parts[0]/parts[1])
      // 例如："1" + "/" + "0" = "1/0"
      const slotKey = `${parts[0]}/${parts[1]}`;

      // 如果该槽位组不存在，创建新的空数组
      if (!groups.has(slotKey)) {
        groups.set(slotKey, []);
      }

      // 将端口添加到对应的槽位组中
      groups.get(slotKey)!.push(port);
    }
  });

  // 此时 groups 的结构示例：
  // Map {
  //   "1/0" => [{ portName: "1/0/3" }, { portName: "1/0/1" }],
  //   "2/0" => [{ portName: "2/0/2" }, { portName: "2/0/1" }],
  //   "1/1" => [{ portName: "1/1/1" }]
  // }

  // 第三步：对槽位组进行排序并处理每组内的端口排序
  return Array.from(groups.entries()) // 转换为数组：[["1/0", [...]], ["2/0", [...]], ["1/1", [...]]]
    .sort(([a], [b]) => {
      // 解析槽位键进行数值排序
      // 例如："1/0" -> [1, 0], "2/0" -> [2, 0]
      const [slotA, subA] = a.split('/').map(Number);
      const [slotB, subB] = b.split('/').map(Number);

      // 首先按槽位号排序，如果相同则按子卡号排序
      // 排序结果："1/0" -> "1/1" -> "2/0"
      return slotA - slotB || subA - subB;
    })
    .map(([slotKey, ports]) => ({
      slotKey, // 槽位标识，如 "1/0"
      ports: ports.sort((a, b) => {
        // 对每个槽位组内的端口按接口序号排序
        // 提取接口序号："1/0/3" -> "3" -> 3
        const portNumA = parseInt(a.portName.split('/')[2]);
        const portNumB = parseInt(b.portName.split('/')[2]);

        // 按接口序号升序排列：端口1 -> 端口2 -> 端口3
        return portNumA - portNumB;
      }),
    }));

  // 最终返回结果示例：
  // [
  //   {
  //     slotKey: "1/0",
  //     ports: [{ portName: "1/0/1" }, { portName: "1/0/3" }]
  //   },
  //   {
  //     slotKey: "1/1",
  //     ports: [{ portName: "1/1/1" }]
  //   },
  //   {
  //     slotKey: "2/0",
  //     ports: [{ portName: "2/0/1" }, { portName: "2/0/2" }]
  //   }
  // ]
});

/**
 * 获取端口状态样式类
 *
 * @param port 端口信息对象
 * @returns 对应的CSS类名
 *
 * 状态映射：
 * - upDown = 1: 端口启用 -> 'port-up' (绿色)
 * - upDown = 2: 端口禁用 -> 'port-down' (红色)
 * - 其他值: 状态未知 -> 'port-unknown' (黄色)
 *
 * 示例：
 * getPortStatusClass({upDown: 1}) -> 'port-up'
 * getPortStatusClass({upDown: 2}) -> 'port-down'
 * getPortStatusClass({upDown: 0}) -> 'port-unknown'
 */
const getPortStatusClass = (port: NdmSwitchPortInfo) => {
  if (port.upDown === 1) {
    return 'port-up';
  } else if (port.upDown === 2) {
    return 'port-down';
  }
  return 'port-unknown';
};
</script>

<template>
  <!-- 主容器：使用 NaiveUI 卡片组件包装整个端口布局 -->
  <NCard v-if="portInfoList.length > 0" size="small" title="端口数据" hoverable>
    <div class="switch-port-layout">
      <!--
        槽位组遍历：根据 groupedPorts 计算属性渲染每个槽位组

        数据结构示例：
        groupedPorts = [
          { slotKey: "1/0", ports: [port1, port2, ...] },
          { slotKey: "1/1", ports: [port3, port4, ...] },
          { slotKey: "2/0", ports: [port5, port6, ...] }
        ]
      -->
      <div v-for="group in groupedPorts" :key="group.slotKey" class="slot-group">
        <!-- 槽位标题：显示槽位标识和端口数量统计 -->
        <div class="slot-header">
          <span class="slot-title">槽位 {{ group.slotKey }}</span>
          <span class="port-count">({{ group.ports.length }}个端口)</span>
        </div>

        <NGrid :cols="Math.ceil(group.ports.length / 2)" :x-gap="8" :y-gap="8" class="port-grid">
          <!--
            布局映射逻辑：实现两行纵向优先的Grid布局

            示例：假设有6个端口 [port1, port2, port3, port4, port5, port6]

            portIndex:  0    1    2    3    4    5
            gridRow:    1    2    1    2    1    2  ((portIndex % 2) + 1)
            gridColumn: 1    1    2    2    3    3  (Math.floor(portIndex / 2) + 1)

            最终布局效果：
            第1行：port1  port3  port5
            第2行：port2  port4  port6

            这样实现了纵向优先填充的两行布局
          -->
          <NGridItem
            v-for="(port, portIndex) in group.ports"
            :key="port.portName"
            :style="{
              gridRow: (portIndex % 2) + 1, // 奇偶索引分别占第1、2行
              gridColumn: Math.floor(portIndex / 2) + 1, // 每两个端口占一列
            }"
          >
            <!--
              端口信息弹窗：使用 NaiveUI Popover 组件显示详细信息

              触发方式：hover（悬停触发）
              位置：top（在端口项上方显示）
            -->
            <NPopover trigger="hover" placement="top">
              <template #trigger>
                <!--
                  端口项显示：
                  - 动态应用状态样式类（port-up/port-down/port-unknown）
                  - 显示端口接口序号（从完整端口名 x/y/z 中提取 z 部分）
                  - 状态指示器圆点
                -->
                <div class="port-item" :class="getPortStatusClass(port)">
                  <div class="port-name">{{ port.portName.split('/')[2] }}</div>
                  <div class="port-status-indicator"></div>
                </div>
              </template>

              <!--
                弹窗内容：显示端口的详细信息

                信息包括：
                1. 完整端口名称
                2. 端口状态（启用/禁用/未知）
                3. 上行速率（使用 transformPortSpeed 函数计算）
                4. 下行速率（使用 transformPortSpeed 函数计算）
                5. 总速率（使用 transformPortSpeed 函数计算）
              -->
              <div class="port-popover-content">
                <div class="port-info-row">
                  <span class="label">端口:</span>
                  <span class="value">{{ port.portName }}</span>
                </div>
                <div class="port-info-row">
                  <span class="label">状态:</span>
                  <span class="value" :class="getPortStatusClass(port)">
                    {{ port.upDown === 1 ? '启用' : port.upDown === 2 ? '禁用' : '未知' }}
                  </span>
                </div>
                <div class="port-info-row">
                  <span class="label">上行速率:</span>
                  <span class="value">{{ transformPortSpeed(port, 'out') }}</span>
                </div>
                <div class="port-info-row">
                  <span class="label">下行速率:</span>
                  <span class="value">{{ transformPortSpeed(port, 'in') }}</span>
                </div>
                <div class="port-info-row">
                  <span class="label">总速率:</span>
                  <span class="value">{{ transformPortSpeed(port, 'total') }}</span>
                </div>
              </div>
            </NPopover>
          </NGridItem>
        </NGrid>
      </div>
    </div>
  </NCard>
</template>

<style scoped lang="scss">
/*
 * 交换机端口布局样式
 *
 * 设计理念：
 * 1. 简约清晰的视觉风格
 * 2. 直观的端口状态指示
 * 3. 良好的交互体验
 * 4. 亮色/暗色模式适配
 */
.switch-port-layout {
  /* 槽位组容器 - 每个槽位之间保持适当间距 */
  .slot-group {
    margin-bottom: 24px;

    &:last-child {
      margin-bottom: 0; // 最后一个槽位组不需要下边距
    }
  }

  /* 槽位标题头部 - 显示槽位信息和端口数量 */
  .slot-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border-color); // 使用主题变量适配亮暗模式

    .slot-title {
      font-weight: 600;
      font-size: 14px;
      color: var(--text-color-1); // 主要文本颜色
    }

    .port-count {
      font-size: 12px;
      color: var(--text-color-3); // 次要文本颜色
    }
  }

  /* 端口网格容器 - 限制最大宽度防止过度拉伸 */
  .port-grid {
    max-width: 100%;
  }

  /*
   * 端口项样式 - 核心视觉元素
   *
   * 尺寸设计：48x36px，适合显示端口号和状态指示器
   * 状态指示：通过边框颜色和圆点颜色区分端口状态
   * 交互效果：悬停时轻微上移和阴影效果
   */
  .port-item {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 48px; // 固定宽度确保布局一致性
    height: 36px; // 固定高度确保视觉平衡
    border: 1px solid var(--border-color);
    border-radius: 4px;
    background: var(--card-color);
    cursor: pointer;
    transition: all 0.2s ease; // 平滑的交互动画

    /* 悬停效果 - 提升交互体验 */
    &:hover {
      transform: translateY(-1px); // 轻微上移
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); // 添加阴影
    }

    /* 端口名称显示 - 只显示接口序号部分 */
    .port-name {
      font-size: 11px;
      font-weight: 500;
      color: var(--text-color-2);
      line-height: 1; // 紧凑行高
    }

    /* 端口状态指示器 - 小圆点显示状态 */
    .port-status-indicator {
      width: 6px;
      height: 6px;
      border-radius: 50%;
      margin-top: 2px;
    }

    /* 端口启用状态 - 绿色主题 */
    &.port-up {
      border-color: #18a058; // NaiveUI 成功色

      .port-status-indicator {
        background-color: #18a058;
      }

      &:hover {
        background-color: rgba(24, 160, 88, 0.05); // 浅绿色背景
      }
    }

    /* 端口禁用状态 - 红色主题 */
    &.port-down {
      border-color: #d03050; // NaiveUI 错误色

      .port-status-indicator {
        background-color: #d03050;
      }

      &:hover {
        background-color: rgba(208, 48, 80, 0.05); // 浅红色背景
      }
    }

    /* 端口未知状态 - 黄色主题 */
    &.port-unknown {
      border-color: #f0a020; // NaiveUI 警告色

      .port-status-indicator {
        background-color: #f0a020;
      }

      &:hover {
        background-color: rgba(240, 160, 32, 0.05); // 浅黄色背景
      }
    }
  }
}

/*
 * 端口信息弹窗内容样式
 *
 * 功能：显示端口的详细信息，包括状态和速率数据
 * 布局：标签-值的两列布局，右对齐数值便于对比
 */
.port-popover-content {
  min-width: 160px; // 确保弹窗有足够宽度显示内容

  .port-info-row {
    display: flex;
    justify-content: space-between; // 标签和值分别左右对齐
    align-items: center;
    margin-bottom: 6px;

    &:last-child {
      margin-bottom: 0; // 最后一行不需要下边距
    }

    /* 信息标签样式 - 统一的次要文本样式 */
    .label {
      font-size: 12px;
      color: var(--text-color-3); // 次要文本颜色
      margin-right: 12px;
    }

    /* 信息值样式 - 突出显示的数据 */
    .value {
      font-size: 12px;
      font-weight: 500; // 稍微加粗突出数值
      color: var(--text-color-2);

      /* 状态值的颜色区分 - 与端口项状态颜色保持一致 */
      &.port-up {
        color: #18a058; // 启用状态：绿色
      }

      &.port-down {
        color: #d03050; // 禁用状态：红色
      }

      &.port-unknown {
        color: #f0a020; // 未知状态：黄色
      }
    }
  }
}

/*
 * 暗色模式适配
 *
 * 针对系统暗色模式的特殊样式调整
 * 主要调整阴影效果，使其在暗色背景下更加明显
 */
@media (prefers-color-scheme: dark) {
  .switch-port-layout {
    .port-item {
      &:hover {
        /* 暗色模式下使用白色阴影替代黑色阴影 */
        box-shadow: 0 2px 8px rgba(255, 255, 255, 0.1);
      }
    }
  }
}
</style>
