import { describe, expect, it } from "vitest";
import { ROBOT_STATUS_TONES } from "@/lib/config";
import { THEME_TOKENS } from "@/lib/theme";
import { statusColor } from "@/lib/theme-status";

describe("statusColor", () => {
  it("設定値にあるキーは対応する色を返す", () => {
    expect(statusColor("dark", "待機中")).toBe(THEME_TOKENS.dark.ok);
    expect(statusColor("dark", "充電中")).toBe(THEME_TOKENS.dark.pr);
    expect(statusColor("dark", "ハンドルアップ")).toBe(THEME_TOKENS.dark.ng);
    expect(statusColor("dark", "セキュリティ有効")).toBe(THEME_TOKENS.dark.ac);
  });

  it("★設定値に無いキーはグレー（c.txD）を返す★（実データで起きること。D-077と同じ思想）", () => {
    expect(statusColor("dark", "UnknownStatus")).toBe(THEME_TOKENS.dark.txD);
    expect(statusColor("light", "EmergencyStop")).toBe(THEME_TOKENS.light.txD);
    expect(statusColor("dark", "Handrail Lifted")).toBe(THEME_TOKENS.dark.txD);
    // `Standby.` は ROBOT_STATUS_TONES にあえて登録していない（lib/config/index.ts のコメント参照）
    expect(statusColor("dark", "Standby.")).toBe(THEME_TOKENS.dark.txD);
  });

  it("空文字もグレーを返す", () => {
    expect(statusColor("dark", "")).toBe(THEME_TOKENS.dark.txD);
  });

  it("前後に空白のある値はグレーを返す（trim しない。値を加工しないのが D-077 の方針）", () => {
    expect(statusColor("dark", " 待機中 ")).toBe(THEME_TOKENS.dark.txD);
    expect(statusColor("dark", "待機中 ")).toBe(THEME_TOKENS.dark.txD);
    expect(statusColor("light", " 待機中")).toBe(THEME_TOKENS.light.txD);
  });

  // ★`ROBOT_STATUS_TONES` はプレーンなオブジェクトリテラルなので、
  //   ガードなしの添字アクセスだと `Object.prototype` のメンバーを拾ってしまい、
  //   後段で `undefined` に落ちて `Pill` が `background:undefined22` を出していた。
  //   D-077 の生値方針では未知の値が来ることが仕様上の前提なので、
  //   ★プロトタイプ由来のキーでも必ずグレーにフォールバックする★ことを固定する。
  const PROTOTYPE_KEYS = [
    "constructor",
    "toString",
    "__proto__",
    "hasOwnProperty",
    "valueOf",
    "isPrototypeOf",
    "propertyIsEnumerable",
    "toLocaleString",
  ];

  it.each(PROTOTYPE_KEYS)(
    "★Object.prototype 由来のキー %s はグレーを返す（undefined ではない）★",
    (key) => {
      expect(statusColor("dark", key)).toBe(THEME_TOKENS.dark.txD);
      expect(statusColor("light", key)).toBe(THEME_TOKENS.light.txD);
    },
  );

  it("★どのキーでも戻り値は必ず文字列で undefined を含まない★（Pill の style が壊れないこと）", () => {
    const keys = [
      ...Object.keys(ROBOT_STATUS_TONES),
      ...PROTOTYPE_KEYS,
      "",
      " 待機中 ",
      "EmergencyStop",
      "Handrail Lifted",
      "Standby.",
      "-200",
    ];
    for (const theme of ["dark", "light"] as const) {
      for (const key of keys) {
        const color = statusColor(theme, key);
        expect(typeof color).toBe("string");
        expect(color).not.toContain("undefined");
      }
    }
  });

  it("ライト/ダーク両方のテーマでそれぞれのトークンが返る", () => {
    expect(statusColor("light", "待機中")).toBe(THEME_TOKENS.light.ok);
    expect(statusColor("dark", "待機中")).toBe(THEME_TOKENS.dark.ok);
    expect(statusColor("light", "待機中")).not.toBe(statusColor("dark", "待機中"));
  });

  it("ROBOT_STATUS_TONES の全キーが両テーマで色を返す（網羅の裏取り）", () => {
    for (const status of Object.keys(ROBOT_STATUS_TONES)) {
      expect(statusColor("dark", status)).not.toBe(THEME_TOKENS.dark.txD);
      expect(statusColor("light", status)).not.toBe(THEME_TOKENS.light.txD);
    }
  });
});
