import { describe, it, expect } from "vitest";
import {
  computeAlert,
  alertStyle,
  trendDirection,
  agpStatusAndSummary,
  kgToLb,
  fToC,
  readingValueSummary,
  DEFAULT_AGP_THRESHOLDS,
} from "../lib/health-data";
import type { Reading } from "../lib/health-data";

// ─── Alert computation ────────────────────────────────────────────────────────

describe("computeAlert", () => {
  it("returns OK for normal BP", () => {
    expect(computeAlert({ systolicBP: 118, diastolicBP: 76 })).toBe("OK");
  });

  it("flags High BP when systolic ≥ 140", () => {
    expect(computeAlert({ systolicBP: 145, diastolicBP: 85 })).toContain("High BP");
  });

  it("flags Critical BP when systolic ≥ 180", () => {
    expect(computeAlert({ systolicBP: 185, diastolicBP: 90 })).toContain("Critical BP");
  });

  it("flags Critical BP when diastolic ≥ 120", () => {
    expect(computeAlert({ systolicBP: 150, diastolicBP: 125 })).toContain("Critical BP");
  });

  it("flags Heart Rate when HR < 50", () => {
    expect(computeAlert({ heartRate: 45 })).toContain("Heart Rate");
  });

  it("flags Heart Rate when HR > 120", () => {
    expect(computeAlert({ heartRate: 130 })).toContain("Heart Rate");
  });

  it("flags Low Blood Oxygen when SpO2 < 92", () => {
    expect(computeAlert({ spo2: 88 })).toContain("Low Blood Oxygen");
  });

  it("flags Glucose when blood glucose < 70", () => {
    expect(computeAlert({ bloodGlucose: 60 })).toContain("Glucose");
  });

  it("flags Glucose when blood glucose > 180", () => {
    expect(computeAlert({ bloodGlucose: 200 })).toContain("Glucose");
  });

  it("flags Temp when temperature ≥ 100.4°F", () => {
    expect(computeAlert({ temperatureF: 101.2 })).toContain("Temp");
  });

  it("returns OK for normal temperature", () => {
    expect(computeAlert({ temperatureF: 98.6 })).toBe("OK");
  });

  it("can combine multiple alerts", () => {
    const result = computeAlert({ systolicBP: 185, heartRate: 130 });
    expect(result).toContain("Critical BP");
    expect(result).toContain("Heart Rate");
  });
});

// ─── Alert style ─────────────────────────────────────────────────────────────

describe("alertStyle", () => {
  it("returns Normal for OK", () => {
    expect(alertStyle("OK").severity).toBe("Normal");
  });

  it("returns Critical for Critical BP", () => {
    expect(alertStyle("Critical BP").severity).toBe("Critical");
  });

  it("returns Warning for High BP", () => {
    expect(alertStyle("High BP").severity).toBe("Warning");
  });

  it("returns Warning for Glucose", () => {
    expect(alertStyle("Glucose").severity).toBe("Warning");
  });
});

// ─── Trend direction ──────────────────────────────────────────────────────────

describe("trendDirection", () => {
  it("shows Stable when values are equal", () => {
    expect(trendDirection("BP", 120, 120).word).toBe("Stable");
  });

  it("shows Improving for BP when value decreases", () => {
    expect(trendDirection("BP", 115, 130).word).toBe("Improving");
  });

  it("shows Worsening for BP when value increases", () => {
    expect(trendDirection("BP", 145, 120).word).toBe("Worsening");
  });

  it("shows Improving for SpO2 when value increases", () => {
    expect(trendDirection("SpO2", 98, 95).word).toBe("Improving");
  });

  it("shows Worsening for SpO2 when value decreases", () => {
    expect(trendDirection("SpO2", 92, 98).word).toBe("Worsening");
  });

  it("returns Stable when either value is null", () => {
    expect(trendDirection("BP", null, 120).word).toBe("Stable");
    expect(trendDirection("BP", 120, null).word).toBe("Stable");
  });
});

// ─── AGP status ───────────────────────────────────────────────────────────────

describe("agpStatusAndSummary", () => {
  it("returns Not Imported when no data", () => {
    expect(agpStatusAndSummary(null).label).toBe("Not Imported");
  });

  it("returns Green when all metrics are in range", () => {
    const result = agpStatusAndSummary(
      { tir: "75", gmi: "6.5", var: "30" },
      DEFAULT_AGP_THRESHOLDS,
    );
    expect(result.color).toBe("ok");
  });

  it("returns Yellow when TIR is below green threshold", () => {
    const result = agpStatusAndSummary(
      { tir: "60", gmi: "6.5", var: "30" },
      DEFAULT_AGP_THRESHOLDS,
    );
    expect(result.color).toBe("warn");
  });

  it("returns Red when TIR is critically low", () => {
    const result = agpStatusAndSummary(
      { tir: "40", gmi: "6.5", var: "30" },
      DEFAULT_AGP_THRESHOLDS,
    );
    expect(result.color).toBe("crit");
  });

  it("returns Red when GMI is high", () => {
    const result = agpStatusAndSummary(
      { tir: "75", gmi: "9.0", var: "30" },
      DEFAULT_AGP_THRESHOLDS,
    );
    expect(result.color).toBe("crit");
  });
});

// ─── Auto-calc ────────────────────────────────────────────────────────────────

describe("kgToLb", () => {
  it("converts 70 kg to approximately 154.3 lb", () => {
    expect(kgToLb(70)).toBeCloseTo(154.3, 0);
  });

  it("converts 100 kg to approximately 220.5 lb", () => {
    expect(kgToLb(100)).toBeCloseTo(220.5, 0);
  });
});

describe("fToC", () => {
  it("converts 98.6°F to 37.0°C", () => {
    expect(fToC(98.6)).toBeCloseTo(37.0, 1);
  });

  it("converts 100.4°F to 38.0°C", () => {
    expect(fToC(100.4)).toBeCloseTo(38.0, 1);
  });
});

// ─── Reading value summary ────────────────────────────────────────────────────

describe("readingValueSummary", () => {
  const base: Reading = {
    id: "1",
    date: "2026-01-01",
    time: "08:00",
    patientName: "Test",
    readingType: "BP",
    context: "",
    deviceMethod: "",
    notes: "",
    alertStatus: "OK",
  };

  it("formats BP correctly", () => {
    expect(readingValueSummary({ ...base, readingType: "BP", systolicBP: 120, diastolicBP: 80 }))
      .toBe("120/80 mmHg");
  });

  it("formats Heart Rate correctly", () => {
    expect(readingValueSummary({ ...base, readingType: "Heart Rate", heartRate: 72 }))
      .toBe("72 BPM");
  });

  it("formats SpO2 with optional HR", () => {
    const val = readingValueSummary({ ...base, readingType: "SpO2", spo2: 98, heartRate: 70 });
    expect(val).toContain("98%");
    expect(val).toContain("70 BPM");
  });

  it("formats Glucose correctly", () => {
    expect(readingValueSummary({ ...base, readingType: "Glucose", bloodGlucose: 95 }))
      .toBe("95 mg/dL");
  });

  it("formats Weight with both units", () => {
    const val = readingValueSummary({ ...base, readingType: "Weight", weightKg: 70, weightLb: 154.3 });
    expect(val).toContain("70 kg");
    expect(val).toContain("154.3 lb");
  });

  it("formats Temperature in Fahrenheit", () => {
    expect(readingValueSummary({ ...base, readingType: "Temperature", temperatureF: 98.6 }))
      .toBe("98.6 °F");
  });

  it("formats HRV correctly", () => {
    expect(readingValueSummary({ ...base, readingType: "HRV", hrv: 55 }))
      .toBe("55 ms");
  });

  it("formats Sleep correctly", () => {
    expect(readingValueSummary({ ...base, readingType: "Sleep", sleepHours: 7.5 }))
      .toBe("7.5 hrs");
  });
});
