import { describe, it, expect } from "vitest";
import { getDayInfo, solarToLunar, lunarToSolar, buildMonthGrid, findGoodDays } from "./engine";

describe("getDayInfo", () => {
  it("returns translated day info for 2026-05-30", () => {
    const info = getDayInfo("2026-05-30");
    expect(info.solarDate).toBe("2026-05-30");
    expect(info.lunarDate.year).toBe(2026);
    expect(info.lunarDate.month).toBe(4);
    expect(info.lunarDate.day).toBe(14);
    expect(info.yearGanZhi).toBe("Bính Ngọ");
    expect(info.dayGanZhi).toBe("Giáp Thìn");
    expect(info.dayBranch).toBe("Thìn");
    expect(info.yearZodiac).toBe("Ngựa");
    expect(info.truc).toBe("Bế");
    expect(info.tianshen?.vi).toBe("Tư Mệnh");
    expect(info.tianshen?.tone).toBe("Hoàng đạo");
    expect(info.isHoangDaoDay).toBe(true);
    expect(info.yi).toContain("Cưới hỏi");
    expect(info.ji).toContain("Lợp mái");
  });

  it("translates most Yi/Ji activities (>=70% non-Chinese)", () => {
    const info = getDayInfo("2026-05-30");
    const all = [...info.yi, ...info.ji];
    const translated = all.filter((s) => !/[\u4e00-\u9fff]/.test(s));
    expect(all.length).toBeGreaterThan(0);
    // Allow ~30% pass-through for rare terms not in dict
    expect(translated.length / all.length).toBeGreaterThanOrEqual(0.7);
  });

  it("returns 12 unique hours Tý..Hợi", () => {
    const info = getDayInfo("2026-05-30");
    expect(info.allHours).toHaveLength(12);
    const branches = info.allHours.map((h) => h.branch);
    expect(branches[0]).toBe("Tý");
    expect(branches[branches.length - 1]).toBe("Hợi");
    expect(new Set(branches).size).toBe(12);
  });

  it("identifies Hoàng đạo hours", () => {
    const info = getDayInfo("2026-05-30");
    expect(info.hoangDaoHours.length).toBeGreaterThan(0);
    info.hoangDaoHours.forEach((h) => {
      expect(h.isHoang).toBe(true);
      expect(h.tianshen?.tone).toBe("Hoàng đạo");
    });
  });
});

describe("solarToLunar / lunarToSolar", () => {
  it("converts solar to lunar", () => {
    const r = solarToLunar("1990-3-15");
    expect(r.year).toBe(1990);
    expect(r.month).toBe(2);
    expect(r.day).toBe(19);
  });

  it("round-trips lunar 1990-2-19 → solar 1990-3-15", () => {
    const s = lunarToSolar(1990, 2, 19);
    expect(s.iso).toBe("1990-03-15");
  });
});

describe("buildMonthGrid", () => {
  it("builds 42 cells for May 2026", () => {
    const cells = buildMonthGrid(2026, 5, "2026-05-30");
    expect(cells).toHaveLength(42);
    const today = cells.find((c) => c.isToday);
    expect(today?.iso).toBe("2026-05-30");
    expect(today?.isCurrentMonth).toBe(true);
    const inMonth = cells.filter((c) => c.isCurrentMonth);
    expect(inMonth).toHaveLength(31); // May has 31 days
  });
});

describe("findGoodDays", () => {
  it("finds wedding-good days in a 60-day range", () => {
    const hits = findGoodDays("wedding", "2026-06-01", "2026-07-31", 30);
    expect(hits.length).toBeGreaterThan(0);
    hits.forEach((h) => {
      expect(h.yiHits.length).toBeGreaterThan(0);
      expect(h.iso >= "2026-06-01" && h.iso <= "2026-07-31").toBe(true);
    });
    // Sorted by score desc
    for (let i = 1; i < hits.length; i++) {
      expect(hits[i - 1].score).toBeGreaterThanOrEqual(hits[i].score);
    }
  });

  it("returns empty for invalid range", () => {
    const hits = findGoodDays("wedding", "2026-08-01", "2026-07-01", 10);
    expect(hits).toEqual([]);
  });
});
