import { describe, expect, it } from "vitest";
import { METRIC_COUNTER } from "@/lib/constants/metrics";
import {
  computeP95,
  computeRate,
  computeRates,
  type MetricsCounters,
} from "@/modules/metrics/collector";

function emptyCounters(): MetricsCounters {
  return {
    [METRIC_COUNTER.POST_TOTAL]: 0,
    [METRIC_COUNTER.POST_DONE]: 0,
    [METRIC_COUNTER.CACHE_HIT_L1]: 0,
    [METRIC_COUNTER.CACHE_HIT_L2]: 0,
    [METRIC_COUNTER.RPA_TRIGGERED]: 0,
    [METRIC_COUNTER.RPA_DONE]: 0,
    [METRIC_COUNTER.DONE_TOTAL]: 0,
    [METRIC_COUNTER.DONE_REALTIME]: 0,
  };
}

describe("computeRates (GD-4)", () => {
  it("100 次 mock：80 done / 100 post → api 80%", () => {
    const counters: MetricsCounters = {
      ...emptyCounters(),
      [METRIC_COUNTER.POST_TOTAL]: 100,
      [METRIC_COUNTER.POST_DONE]: 80,
    };
    expect(computeRates(counters).api_success_rate).toBe(80);
  });

  it("RPA 85/100 → rpa_success_rate 85%", () => {
    const counters: MetricsCounters = {
      ...emptyCounters(),
      [METRIC_COUNTER.RPA_TRIGGERED]: 100,
      [METRIC_COUNTER.RPA_DONE]: 85,
    };
    expect(computeRates(counters).rpa_success_rate).toBe(85);
  });

  it("realtime 90/100 done → realtime_rate 90%", () => {
    const counters: MetricsCounters = {
      ...emptyCounters(),
      [METRIC_COUNTER.DONE_TOTAL]: 100,
      [METRIC_COUNTER.DONE_REALTIME]: 90,
    };
    expect(computeRates(counters).realtime_rate).toBe(90);
  });

  it("cache (L1+L2) 90/100 post → cache_hit_rate 90%", () => {
    const counters: MetricsCounters = {
      ...emptyCounters(),
      [METRIC_COUNTER.POST_TOTAL]: 100,
      [METRIC_COUNTER.CACHE_HIT_L1]: 40,
      [METRIC_COUNTER.CACHE_HIT_L2]: 50,
    };
    expect(computeRates(counters).cache_hit_rate).toBe(90);
  });

  it("分母为 0 → 返回 0", () => {
    expect(computeRate(10, 0)).toBe(0);
    expect(computeRates(emptyCounters()).api_success_rate).toBe(0);
  });
});

describe("computeP95", () => {
  it("100 样本 P95 取第 95 百分位", () => {
    const samples = Array.from({ length: 100 }, (_, index) => index + 1);
    expect(computeP95(samples)).toBe(95);
  });

  it("空样本 → 0", () => {
    expect(computeP95([])).toBe(0);
  });
});
