import {
  buildHealthRiskReportData,
  getProbabilityAtYear,
  getRiskBandIndex,
  PRIORITY_PIPE_LIMIT,
} from "./healthRiskReport";
import { PredictionResult } from "./types";

const createResult = (
  linkId: string,
  years: number[],
  probabilities: number[],
): PredictionResult => ({
  link_id: linkId,
  survival_function: {
    x: years,
    y: probabilities,
    a: 0,
    b: 0,
  },
});

describe("healthRiskReport", () => {
  it("matches probability by the exact forecast year", () => {
    const result = createResult("P-1", [4, 6], [0.8, 0.2]);

    expect(getProbabilityAtYear(result, 6)).toBe(0.2);
    expect(getProbabilityAtYear(result, 5)).toBeNull();
  });

  it("rejects missing and out-of-range probabilities", () => {
    expect(
      getProbabilityAtYear(createResult("P-1", [4], [Number.NaN]), 4),
    ).toBeNull();
    expect(getProbabilityAtYear(createResult("P-2", [4], [1.1]), 4)).toBeNull();
  });

  it("keeps risk break boundaries consistent with the existing legend", () => {
    expect(getRiskBandIndex(0)).toBe(0);
    expect(getRiskBandIndex(0.1)).toBe(0);
    expect(getRiskBandIndex(0.10001)).toBe(1);
    expect(getRiskBandIndex(1)).toBe(9);
  });

  it("builds the current snapshot and high-risk trend", () => {
    const report = buildHealthRiskReportData(
      [
        createResult("P-1", [4, 5], [0.2, 0.1]),
        createResult("P-2", [4, 5], [0.5, 0.25]),
        createResult("P-3", [4, 5], [0.9, 0.8]),
        createResult("P-4", [5], [0.4]),
      ],
      4,
    );

    expect(report.totalCount).toBe(4);
    expect(report.validCount).toBe(3);
    expect(report.invalidCount).toBe(1);
    expect(report.highRiskCount).toBe(1);
    expect(report.highRiskRatio).toBeCloseTo(1 / 3);
    expect(report.averageProbability).toBeCloseTo(0.533333);
    expect(report.distribution.reduce((sum, item) => sum + item.count, 0)).toBe(
      3,
    );
    expect(report.trend).toEqual([
      { year: 4, count: 1, validCount: 3, ratio: 1 / 3 },
      { year: 5, count: 2, validCount: 4, ratio: 0.5 },
    ]);
  });

  it("sorts priority pipes and limits the printed detail", () => {
    const results = Array.from({ length: PRIORITY_PIPE_LIMIT + 5 }, (_, index) =>
      createResult(`P-${PRIORITY_PIPE_LIMIT + 5 - index}`, [4], [0.2]),
    );

    const report = buildHealthRiskReportData(results, 4);

    expect(report.priorityPipes).toHaveLength(PRIORITY_PIPE_LIMIT);
    expect(report.priorityPipes[0].linkId).toBe("P-1");
    expect(report.priorityPipes.at(-1)?.linkId).toBe(
      `P-${PRIORITY_PIPE_LIMIT}`,
    );
  });
});
