<template>
  <!-- 纯数据组件：不渲染 UI，提供 CPU hover 信息 -->
  <div style="display: none"></div>
</template>

<script setup lang="ts">
/**
 * CPU 悬浮信息提供者
 * - 直接调用 /UI/Rest/System/Processor 获取 CPU 列表
 * - 构建 hover 用的 KV 对，并把 CPU 名称列表上报给 threeDui
 */
import { ref, reactive, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { loading } from '@/utils/composition';

import type { KV } from '../shared/types';
import { firstNonEmpty, fmt, fmtCoreThread, fmtCacheTriple } from '../shared/format';

const emit = defineEmits<{
  (e: 'cpu-list', names: string[]): void;
}>();

/* ======================= CPU 数据缓存 ======================= */
const cpuNames = ref<string[]>([]);
const cpuBasicMap = reactive<Record<string, string>>({});
const cpuDetailMap = reactive<Record<string, Record<string, any>>>({});

const { t } = useI18n();

/* 工具标签 */
const labelCores = t('CORE_WITH_UNIT') || 'cores';
const labelThrds = t('THREAD_WITH_UNIT') || 'threads';
const _fmtCoreThread = (c: any, th: any) => fmtCoreThread(c, th, labelCores, labelThrds);

/* ========== 初始化列表：直接从 /UI/Rest/System/Processor 取数据 ========== */
async function initCpus() {
  loading?.(true);
  try {
    const resp = await fetch('/UI/Rest/System/Processor', {
      headers: { Accept: 'application/json' },
    });

    const data = await resp.json().catch(() => ({}));
    const list = ((data && (data.CPU || data.List || data.Processors)) || []) as any[];

    cpuNames.value = [];
    Object.keys(cpuBasicMap).forEach(k => delete cpuBasicMap[k]);
    Object.keys(cpuDetailMap).forEach(k => delete cpuDetailMap[k]);

    list.forEach((g: any, idx: number) => {
      if (!g) {
        return;
      }

      const name = firstNonEmpty(g.DeviceLocator, g.Name, `CPU${idx + 1}`);
      const position = firstNonEmpty(g.Position, 'CpuBoard1');
      const manufacturer = firstNonEmpty(g.Manufacturer);
      const model = firstNonEmpty(g.Model);
      const freqMHz = fmt(firstNonEmpty(g.FrequencyMHz, g.Frequency), 'MHz');
      const id = firstNonEmpty(g.Identification, g.ProcessorId, g.Id);

      const totalCores = firstNonEmpty(g.TotalCores);
      const totalThreads = firstNonEmpty(g.TotalThreads);
      const enabledCores = firstNonEmpty(g.TotalEnabledCores, g.TotalCores);
      const enabledThreads = firstNonEmpty(g.TotalEnabledThreads, g.TotalThreads);

      const totalCStr = _fmtCoreThread(totalCores, totalThreads);
      const enabledCStr = _fmtCoreThread(enabledCores, enabledThreads);

      const cacheTriple = fmtCacheTriple(
        firstNonEmpty(g.L1CacheKiB),
        firstNonEmpty(g.L2CacheKiB),
        firstNonEmpty(g.L3CacheKiB),
        'KB',
      );
      const cacheKiB = firstNonEmpty(g.CacheKiB, cacheTriple);

      const state = firstNonEmpty(g.State, 'Present');
      const partNumber = firstNonEmpty(g.PartNumber, 'Unknown');
      const serialNumber = firstNonEmpty(g.SerialNumber);
      const otherParams = firstNonEmpty(g.OtherParameters, g.Features);

      const mem = g.MemoryOnChip || {};
      const hbmCapacityMiB = fmt(firstNonEmpty(mem.CapacityMiB), 'MB');
      const hbmWidthBits = fmt(firstNonEmpty(mem.DataWidthBits), 'bit');
      const hbmSpeedsMHz = fmt(firstNonEmpty(mem.OperatingSpeedsMHz), 'MHz');

      cpuNames.value.push(name);
      cpuBasicMap[name] = [name, manufacturer, model].filter(Boolean).join(' | ');

      cpuDetailMap[name] = {
        name,
        position,
        manufacturer,
        model,
        id,
        frequencyMHz: freqMHz,
        totalCores: totalCStr,
        totalEnabledCores: enabledCStr,
        cacheKiB,
        processorState: state,
        partNumber,
        serialNumber,
        otherParameters: otherParams,
        hbmCapacityMiB,
        hbmWidthBits,
        hbmSpeedsMHz,
      };
    });

    // 通知 threeDui 有哪些 CPU 名称（用于右侧树和同步）
    emit('cpu-list', cpuNames.value);
  } catch (e) {
    void e;
  } finally {
    loading?.(false);
  }
}

/* ========== 对外：文本与 KV 对 ========== */
function getBasicText(name: string) {
  return cpuBasicMap[name] ?? name;
}

async function buildPairs(name: string): Promise<KV[]> {
  const info = cpuDetailMap[name];
  if (!info) {
    return [];
  }

  const schema: Array<[string, string]> = [
    ['COMMON_NAME', 'name'],
    ['MEMORY_POSITION', 'position'],
    ['COMMON_MANUFACTURER', 'manufacturer'],
    ['PROCESSOR_MODEL', 'model'],
    ['PROCESSOR_ID', 'id'],
    ['PROCESSOR_FREQENCY', 'frequencyMHz'],
    ['PROCESSOR_CORECOUNT_THREADCOUNT', 'totalCores'],
    ['PROCESSOR_ENABLED_CORECOUNT_THREADCOUNT', 'totalEnabledCores'],
    ['PROCESSOR_FDM_ALARM_CACHE', 'cacheKiB'],
    ['PROCESSOR_STATE', 'processorState'],
    ['OTHER_PART_NUMBER', 'partNumber'],
    ['COMMON_SERIALNUMBER', 'serialNumber'],
    ['PROCESSOR_OTHER', 'otherParameters'],
    ['PROCESSOR_HBM_CAP', 'hbmCapacityMiB'],
    ['PROCESSOR_HBM_WIDTH', 'hbmWidthBits'],
    ['PROCESSOR_HBM_SPEED', 'hbmSpeedsMHz'],
  ];

  const pairs = schema
    .map(([label, key]) => {
      const v = (info as any)[key];
      if (v === undefined || v === null || v === '') {
        return null;
      }
      return { k: t(label as any), v: String(v) };
    })
    .filter(Boolean) as KV[];

  return pairs;
}

/**
 * 三维那边在模型加载完成时会调用 cpuRef.value?.refresh?.()
 * 所以这里把 initCpus 暴露成 refresh 方法
 */
defineExpose({
  buildPairs,
  getBasicText,
  refresh: initCpus,
});

onMounted(initCpus);
</script>
