import { describe, expect, it } from "vitest";

import { RESCUE_INITIAL_VISIBLE } from "@/lib/config";
import { rescueVisibility } from "@/lib/dashboard/rescue-visibility";

/**
 * 指示書AJ §4-5 の画面側の期待値表。
 *
 * | # | 該当件数 | 初期表示 | 「もっと表示」 |
 * |---|---|---|---|
 * | 1-7 | 0 | 0行 | ★出さない★（カードは残す） |
 * | 1-8 | 3 | 3行 | ★出さない★ |
 * | 1-9 | ★ちょうど5★ | 5行 | ★★出さない★★ |
 * | 1-10 | 6 | 5行 | ★★出す（あと1件）★★ |
 * | 1-11 | 6 → 押したあと | 6行 | 「閉じる」に変わる |
 *
 * ★★1-9 と 1-10 の両方を入れてある★★ — `>` と `>=` の取り違えが通らないようにするため
 *   （ちょうど5件で「もっと表示」が出ると、押しても1件も増えない）。
 *
 * ★閾値を直書きしない★（`CLAUDE.md` §7）— 件数は `RESCUE_INITIAL_VISIBLE` から作る。
 *   ★設定値を 5 から変えてもこの表の意味が変わらない★。
 */

/** n 件ぶんのダミー行（`rescueVisibility()` は中身を見ないので数値で足りる） */
function items(n: number): number[] {
  return Array.from({ length: n }, (_, i) => i + 1);
}

const N = RESCUE_INITIAL_VISIBLE;

describe("rescueVisibility", () => {
  it("#1-7 0件: 0行・ボタンを出さない", () => {
    const v = rescueVisibility(items(0), false);

    expect(v.visible).toEqual([]);
    expect(v.remaining).toBe(0);
    expect(v.canToggle).toBe(false);
  });

  it("#1-8 初期表示件数より少なければ全部出し、ボタンを出さない", () => {
    const v = rescueVisibility(items(N - 2), false);

    expect(v.visible).toHaveLength(N - 2);
    expect(v.remaining).toBe(0);
    expect(v.canToggle).toBe(false);
  });

  it("#1-9 ★ちょうど初期表示件数のときはボタンを出さない★（押しても増えないため）", () => {
    const v = rescueVisibility(items(N), false);

    expect(v.visible).toHaveLength(N);
    expect(v.remaining).toBe(0);
    expect(v.canToggle).toBe(false);
  });

  it("#1-10 ★1件超えたら初期表示件数だけ出し、残り1件のボタンを出す★", () => {
    const v = rescueVisibility(items(N + 1), false);

    expect(v.visible).toHaveLength(N);
    expect(v.visible).toEqual(items(N));
    expect(v.remaining).toBe(1);
    expect(v.canToggle).toBe(true);
  });

  it("#1-11 開いたら全件出て、ボタンは残る（＝「閉じる」に切り替わる）", () => {
    const v = rescueVisibility(items(N + 1), true);

    expect(v.visible).toHaveLength(N + 1);
    expect(v.remaining).toBe(0);
    // ★開いたあともボタンは消えない★ — 消えると戻せなくなる（指示書AJ 罠5）
    expect(v.canToggle).toBe(true);
  });

  it("★並び順を変えない★（先頭から順に切るだけ）", () => {
    const v = rescueVisibility(["a", "b", "c"], false);

    expect(v.visible).toEqual(["a", "b", "c"]);
  });

  it("★件数が多くても切るのは表示だけ（総数は呼び出し側の items.length）★", () => {
    const v = rescueVisibility(items(50), false);

    expect(v.visible).toHaveLength(N);
    expect(v.remaining).toBe(50 - N);
    expect(v.canToggle).toBe(true);
  });
});
