import { describe, it, expect, beforeEach, vi, afterEach } from "vitest";
import { get } from "svelte/store";
import { characterState, characterInfo } from "./character";

describe("characterState store", () => {
  beforeEach(() => {
    vi.useFakeTimers();
    characterState.reset();
  });

  afterEach(() => {
    vi.useRealTimers();
  });

  describe("initial state", () => {
    it("starts in idle state", () => {
      expect(get(characterState)).toBe("idle");
    });
  });

  describe("setState", () => {
    it("sets the character state", () => {
      characterState.setState("thinking");
      expect(get(characterState)).toBe("thinking");
    });

    it("can set any valid state", () => {
      const states = [
        "idle",
        "thinking",
        "typing",
        "coding",
        "searching",
        "mcp",
        "permission",
        "success",
        "error",
      ] as const;
      for (const state of states) {
        characterState.setState(state);
        expect(get(characterState)).toBe(state);
      }
    });

    it("cancels any active temporary state timer", () => {
      characterState.setTemporaryState("success", 5000);
      characterState.setState("thinking");

      // Advance past the temporary state duration — should stay as thinking
      vi.advanceTimersByTime(6000);
      expect(get(characterState)).toBe("thinking");
    });
  });

  describe("setTemporaryState", () => {
    it("sets the character state immediately", () => {
      characterState.setTemporaryState("success", 2000);
      expect(get(characterState)).toBe("success");
    });

    it("reverts to idle after the specified duration", () => {
      characterState.setTemporaryState("success", 2000);
      vi.advanceTimersByTime(2000);
      expect(get(characterState)).toBe("idle");
    });

    it("uses 2000ms as the default duration", () => {
      characterState.setTemporaryState("error");
      vi.advanceTimersByTime(1999);
      expect(get(characterState)).toBe("error");
      vi.advanceTimersByTime(1);
      expect(get(characterState)).toBe("idle");
    });

    it("cancels a previous temporary state timer when a new one is set", () => {
      characterState.setTemporaryState("success", 5000);
      characterState.setTemporaryState("error", 1000);

      // First timer would have fired at 5000ms but was cancelled
      vi.advanceTimersByTime(1000);
      expect(get(characterState)).toBe("idle");
    });
  });

  describe("reset", () => {
    it("resets the state to idle", () => {
      characterState.setState("thinking");
      characterState.reset();
      expect(get(characterState)).toBe("idle");
    });

    it("cancels any pending temporary state timer", () => {
      characterState.setTemporaryState("success", 5000);
      characterState.reset();

      // Should now be idle and should NOT revert again after timer fires
      expect(get(characterState)).toBe("idle");
      vi.advanceTimersByTime(5000);
      expect(get(characterState)).toBe("idle");
    });
  });
});

describe("characterInfo derived store", () => {
  beforeEach(() => {
    characterState.reset();
  });

  it("returns the info object for the current state", () => {
    const info = get(characterInfo);
    expect(info).toBeDefined();
    expect(typeof info.label).toBe("string");
  });

  it("updates when the character state changes", () => {
    characterState.setState("thinking");
    const thinkingInfo = get(characterInfo);

    characterState.setState("idle");
    const idleInfo = get(characterInfo);

    expect(thinkingInfo.label).not.toBe(idleInfo.label);
  });
});
