import { describe, expect, it } from "vitest";

import { calculateAvailabilityFromMtbfMttr } from "../engine";

/**
 * Tests for calculateAvailabilityFromMtbfMttr (Wertstrom P4, B3,
 * Capability-Matrix, KAR-878/KAR-986) — Availability = MTBF / (MTBF + MTTR).
 *
 * FIXTURE-DATEN-REGEL: every number below is FREE INVENTION.
 */
describe("calculateAvailabilityFromMtbfMttr", () => {
  it("computes the standard MTBF/(MTBF+MTTR) ratio", () => {
    // 90 min uptime, 10 min repair -> 90/100 = 0.9
    expect(calculateAvailabilityFromMtbfMttr(90, 10)).toBe(0.9);
  });

  it("returns 1 (100%) when MTTR is 0 (never fails to repair instantly)", () => {
    expect(calculateAvailabilityFromMtbfMttr(120, 0)).toBe(1);
  });

  it("returns 0 when MTBF is 0 (never up)", () => {
    expect(calculateAvailabilityFromMtbfMttr(0, 30)).toBe(0);
  });

  it("returns null (not 0, not NaN) when both are 0 — nothing to compute", () => {
    expect(calculateAvailabilityFromMtbfMttr(0, 0)).toBeNull();
  });

  it("returns null for a negative input", () => {
    expect(calculateAvailabilityFromMtbfMttr(-5, 10)).toBeNull();
    expect(calculateAvailabilityFromMtbfMttr(10, -5)).toBeNull();
  });

  it("returns null for a non-finite input", () => {
    expect(calculateAvailabilityFromMtbfMttr(NaN, 10)).toBeNull();
    expect(calculateAvailabilityFromMtbfMttr(10, Infinity)).toBeNull();
  });

  // Review-Fix F10 (adversarial review, PR #355): both inputs individually
  // pass Number.isFinite, but their SUM overflows to Infinity — the old
  // `denominator <= 0` guard does not catch that (Infinity is not <= 0), so
  // `mtbfMin / Infinity` silently evaluated to 0 for any finite mtbfMin,
  // fabricating a 0% availability the function's own contract promises
  // never happens.
  it("returns null (not a fabricated 0) when mtbfMin + mttrMin overflows to Infinity, even though both inputs are individually finite", () => {
    expect(Number.isFinite(Number.MAX_VALUE)).toBe(true);
    expect(Number.isFinite(Number.MAX_VALUE + Number.MAX_VALUE)).toBe(false);
    expect(calculateAvailabilityFromMtbfMttr(Number.MAX_VALUE, Number.MAX_VALUE)).toBeNull();
  });

  it("still computes normally for large-but-non-overflowing inputs (the guard doesn't over-trigger)", () => {
    expect(calculateAvailabilityFromMtbfMttr(8e307, 8e307)).toBe(0.5);
  });
});
