import { describe, it, expect } from "vitest";
import {
  computeTamTai,
  computeKimLau,
  computeHoangOc,
  computeFixedHan,
  buildAnnualHanReport,
} from "./han-vn";

describe("Tam Tai", () => {
  it("returns active for trine member at peak year", () => {
    // Thân-Tý-Thìn → Tam Tai năm Dần, Mão, Thìn
    expect(computeTamTai("Thân", "Mão")).toEqual({
      active: true,
      position: 2,
      label: "Chính Tam Tai",
    });
  });
  it("returns active first/exit positions", () => {
    expect(computeTamTai("Tý", "Dần").active).toBe(true);
    expect(computeTamTai("Tý", "Dần")).toMatchObject({ position: 1 });
    expect(computeTamTai("Thìn", "Thìn")).toMatchObject({ position: 3 });
  });
  it("returns inactive when year-branch outside trine band", () => {
    expect(computeTamTai("Thân", "Tỵ")).toEqual({ active: false });
    expect(computeTamTai("Dần", "Sửu")).toEqual({ active: false });
  });
  it("covers all four trines", () => {
    // Dần-Ngọ-Tuất → Thân/Dậu/Tuất
    expect(computeTamTai("Dần", "Dậu").active).toBe(true);
    // Hợi-Mão-Mùi → Tỵ/Ngọ/Mùi
    expect(computeTamTai("Mão", "Ngọ").active).toBe(true);
    // Tỵ-Dậu-Sửu → Hợi/Tý/Sửu
    expect(computeTamTai("Sửu", "Tý").active).toBe(true);
  });
});

describe("Kim Lâu", () => {
  it("active at age%9 ∈ {1,3,6,8}", () => {
    expect(computeKimLau(19)).toMatchObject({ active: true, kind: "Thân" });
    expect(computeKimLau(21)).toMatchObject({ active: true, kind: "Thê" });
    expect(computeKimLau(24)).toMatchObject({ active: true, kind: "Tử" });
    expect(computeKimLau(26)).toMatchObject({ active: true, kind: "Lục Súc" });
  });
  it("inactive at other ages", () => {
    expect(computeKimLau(20)).toEqual({ active: false });
    expect(computeKimLau(25)).toEqual({ active: false });
    expect(computeKimLau(27)).toEqual({ active: false });
  });
  it("guards against age <= 0", () => {
    expect(computeKimLau(0)).toEqual({ active: false });
    expect(computeKimLau(-1)).toEqual({ active: false });
  });
});

describe("Hoàng Ốc", () => {
  it("starts at Nhất Cát at age 10", () => {
    expect(computeHoangOc(10)).toMatchObject({ label: "Nhất Cát", good: true });
    expect(computeHoangOc(11)).toMatchObject({ label: "Nhì Nghi", good: true });
    expect(computeHoangOc(12)).toMatchObject({ label: "Tam Địa Sát", good: false });
    expect(computeHoangOc(13)).toMatchObject({ label: "Tứ Tấn Tài", good: true });
    expect(computeHoangOc(14)).toMatchObject({ label: "Ngũ Thọ Tử", good: false });
    expect(computeHoangOc(15)).toMatchObject({ label: "Lục Hoang Ốc", good: false });
  });
  it("cycles every 6 years", () => {
    expect(computeHoangOc(16)).toMatchObject({ label: "Nhất Cát" });
    expect(computeHoangOc(22)).toMatchObject({ label: "Nhất Cát" });
  });
});

describe("Fixed hạn (Thái Tuế / Tang Môn / Tuế Phá)", () => {
  it("Thái Tuế trùng năm-chi", () => {
    const r = computeFixedHan("Ngọ", "Ngọ");
    expect(r[0]).toMatchObject({ name: "Thái Tuế", branch: "Ngọ", active: true });
  });
  it("Tang Môn = năm-chi + 2", () => {
    const r = computeFixedHan("Thân", "Ngọ"); // Ngọ+2 = Thân
    expect(r[1]).toMatchObject({ name: "Tang Môn", branch: "Thân", active: true });
  });
  it("Tuế Phá = đối xung năm-chi", () => {
    const r = computeFixedHan("Tý", "Ngọ"); // Ngọ+6 = Tý
    expect(r[2]).toMatchObject({ name: "Tuế Phá", branch: "Tý", active: true });
  });
});

describe("buildAnnualHanReport", () => {
  it("aggregates and flags hasBadHan", () => {
    // Born Ngọ (Dần-Ngọ-Tuất trine), age 37 (mod9=1 → Kim Lâu Thân),
    // year Ngọ. Should be heavily afflicted.
    const r = buildAnnualHanReport({ birthBranch: "Ngọ", yearBranch: "Ngọ", age: 37 });
    expect(r.kimLau.active).toBe(true);
    expect(r.fixed[0].active).toBe(true); // Thái Tuế
    expect(r.hasBadHan).toBe(true);
  });
  it("clean year flips hasBadHan false", () => {
    // Born Tý (Thân-Tý-Thìn trine), age 20 (mod9=2 → no Kim Lâu),
    // year Tỵ (outside trine, Hoàng Ốc cycle 16→Nhất Cát actually is good).
    // age 20 → offset 10 → idx 4 → Ngũ Thọ Tử (bad). Pick age 22 instead:
    // 22 → offset 12 → idx 0 → Nhất Cát (good).
    const r = buildAnnualHanReport({ birthBranch: "Tý", yearBranch: "Tỵ", age: 22 });
    expect(r.hasBadHan).toBe(false);
  });
});
