import { describe, expect, it } from "vitest";
import { capConsecutiveDays } from "@/lib/format/consecutive-days";
import { CONSECUTIVE_DAYS_DISPLAY, ESCALATION_THRESHOLDS } from "@/lib/config";
import { judgeEscalationLevel } from "@/lib/judge/escalation";

/**
 * `capConsecutiveDays()` の期待値表テスト（指示書AF 段階2-3。`CLAUDE.md` §9.4）。
 *
 * ★テストに `3` / `30` を直書きしてよいのは「期待値」としてだけ★。
 *   入力側（`maxDays` に渡す下限）は `ESCALATION_THRESHOLDS.level3Days` から取る。
 */

/** 設定できる下限（＝L3 の日数）。★`3` と直書きしない★ */
const LOWER_BOUND = ESCALATION_THRESHOLDS.level3Days;

describe("capConsecutiveDays（表示上限。判定には使わない）", () => {
  // | # | rawDays | maxDays | 期待 days | 期待 capped | 何の境界か |
  const cases: [string, number, number, number, boolean][] = [
    ["#1 上限−1", 29, 30, 29, false],
    ["#2 上限ちょうど（「以上」にしない）", 30, 30, 30, false],
    ["#3 上限+1", 31, 30, 30, true],
    ["#4 十分大きい", 100, 30, 30, true],
    ["#5 下限の境界", LOWER_BOUND, LOWER_BOUND, LOWER_BOUND, false],
    ["#6 下限でも「以上」が出る", LOWER_BOUND + 1, LOWER_BOUND, LOWER_BOUND, true],
    ["#7 問題なし", 0, 30, 0, false],
    ["#8 L1", 1, 30, 1, false],
    ["#9 L2", 2, 30, 2, false],
  ];

  it.each(cases)("%s: raw=%i / max=%i → days=%i / capped=%s", (_label, raw, max, days, capped) => {
    expect(capConsecutiveDays(raw, max)).toEqual({ days, capped });
  });

  // #10 引数省略 → 既定値が使われること
  it("#10 maxDays を省略すると lib/config の既定値が使われる", () => {
    const max = CONSECUTIVE_DAYS_DISPLAY.defaultMax;
    expect(capConsecutiveDays(max)).toEqual({ days: max, capped: false });
    expect(capConsecutiveDays(max + 1)).toEqual({ days: max, capped: true });
    // 省略時と明示時で結果が一致する（既定値の取り違えを固定する）
    expect(capConsecutiveDays(max + 1)).toEqual(capConsecutiveDays(max + 1, max));
  });
});

describe("表示上限が判定を壊さないこと（禁止事項9）", () => {
  // #11 上限を下限まで絞っても、判定は「上限をかける前の生値」で行われ L3 のまま
  it("#11 maxDays を下限にしても judgeEscalationLevel(rawDays) は L3 を返し続ける", () => {
    const rawDays = 5;
    const capped = capConsecutiveDays(rawDays, LOWER_BOUND);

    expect(capped).toEqual({ days: LOWER_BOUND, capped: true });
    // ★判定に渡すのは生値★。頭打ちにした `capped.days` ではない
    expect(judgeEscalationLevel(rawDays)).toBe("L3");
    // 頭打ち後の値で判定しても L3 なのは「下限 = L3 の日数」だから。
    // ★下限を L3 未満にできないこと（#12）がこの一致を支えている★
    expect(judgeEscalationLevel(capped.days)).toBe("L3");
  });

  // #12 設定同士の関係を固定する
  it("#12 CONSECUTIVE_DAYS_DISPLAY.minMax >= ESCALATION_THRESHOLDS.level3Days", () => {
    expect(CONSECUTIVE_DAYS_DISPLAY.minMax).toBeGreaterThanOrEqual(
      ESCALATION_THRESHOLDS.level3Days
    );
  });
});
