import { describe, expect, it } from "vitest";
import {
  countConsecutiveProblemDays,
  judgeEscalation,
  judgeEscalationLevel,
  type ScheduleDayResult,
} from "@/lib/judge";

/** 読みやすさのための組み立てヘルパー。"1" = 問題あり / "0" = 問題なし */
function days(pattern: string): ScheduleDayResult[] {
  return pattern.split("").map((c, i) => ({
    date: `2026-08-${String(i + 1).padStart(2, "0")}`,
    isProblem: c === "1",
  }));
}

describe("countConsecutiveProblemDays", () => {
  it("直近から遡って連続数を数える", () => {
    expect(countConsecutiveProblemDays(days("1"))).toBe(1);
    expect(countConsecutiveProblemDays(days("11"))).toBe(2);
    expect(countConsecutiveProblemDays(days("111"))).toBe(3);
    expect(countConsecutiveProblemDays(days("11111"))).toBe(5);
  });

  it("最新日が問題なしなら0", () => {
    expect(countConsecutiveProblemDays(days("1110"))).toBe(0);
    expect(countConsecutiveProblemDays(days("0000"))).toBe(0);
  });

  it("途中で問題なしの日があれば、そこで連続は途切れる", () => {
    expect(countConsecutiveProblemDays(days("11011"))).toBe(2);
    expect(countConsecutiveProblemDays(days("10111"))).toBe(3);
  });

  it("空配列は0", () => {
    expect(countConsecutiveProblemDays([])).toBe(0);
  });
});

describe("judgeEscalationLevel", () => {
  const table: Array<{ name: string; consecutive: number; level: string | null }> = [
    { name: "問題なし", consecutive: 0, level: null },
    { name: "初回の問題", consecutive: 1, level: "L1" },
    { name: "2日連続", consecutive: 2, level: "L2" },
    { name: "3日連続", consecutive: 3, level: "L3" },
    { name: "5日連続（長期化してもL3のまま）", consecutive: 5, level: "L3" },
  ];

  it.each(table)("$name: $consecutive日 → $level", ({ consecutive, level }) => {
    expect(judgeEscalationLevel(consecutive)).toBe(level);
  });
});

describe("judgeEscalation — スケジュール存在日ベースの連続 ★最重要★", () => {
  it("スケジュール非存在日を挟んでも連続は途切れない", () => {
    // 月水金スケジュールの施設。8/3(月)・8/5(水)・8/7(金)に清掃予定があり、いずれも失敗。
    // カレンダー上は5日間だが、スケジュール存在日の連続は3日なのでL3。
    //
    // ★この関数には「スケジュール存在日だけ」を渡すこと★
    //   火・木は清掃予定がないため、そもそも配列に含めない。
    const scheduleDays: ScheduleDayResult[] = [
      { date: "2026-08-03", isProblem: true }, // 月
      { date: "2026-08-05", isProblem: true }, // 水
      { date: "2026-08-07", isProblem: true }, // 金
    ];

    const result = judgeEscalation(scheduleDays);
    expect(result.consecutiveDays).toBe(3);
    expect(result.level).toBe("L3");
  });

  it("カレンダー日で数えると誤ってL1になることを確認（アンチパターンの記録）", () => {
    // もし火・木を「問題なし」として配列に含めてしまうと、連続が途切れて L1 になる。
    // データ取得側でスケジュール存在日に絞り込むのを忘れるとこうなる。
    const wrong: ScheduleDayResult[] = [
      { date: "2026-08-03", isProblem: true },
      { date: "2026-08-04", isProblem: false }, // ← 本来含めてはいけない
      { date: "2026-08-05", isProblem: true },
      { date: "2026-08-06", isProblem: false }, // ← 本来含めてはいけない
      { date: "2026-08-07", isProblem: true },
    ];
    expect(judgeEscalation(wrong).level).toBe("L1");
  });

  it("初回の出発失敗はL1", () => {
    expect(judgeEscalation(days("1")).level).toBe("L1");
  });

  it("2日連続△以下はL2", () => {
    expect(judgeEscalation(days("11")).level).toBe("L2");
  });

  it("問題が解消した施設はレベルなし", () => {
    expect(judgeEscalation(days("1110")).level).toBeNull();
  });
});
