import { describe, it, expect, beforeEach } from "vitest";
import { get } from "svelte/store";
import { emitMockEvent } from "../../../vitest.setup";
import { todos, initializeTodoListener, cleanupTodoListener } from "./todos";
import type { TodoItem } from "./todos";

describe("todos store", () => {
  beforeEach(() => {
    cleanupTodoListener();
    todos.clear();
  });

  describe("initial state", () => {
    it("starts with an empty list", () => {
      expect(get(todos)).toEqual([]);
    });
  });

  describe("set and clear", () => {
    it("can set todos directly", () => {
      const items: TodoItem[] = [
        { content: "Task 1", status: "pending", activeForm: "Doing task 1" },
        { content: "Task 2", status: "in_progress", activeForm: "Doing task 2" },
      ];
      todos.set(items);
      expect(get(todos)).toEqual(items);
    });

    it("clear resets to empty array", () => {
      todos.set([{ content: "Task", status: "completed", activeForm: "Doing task" }]);
      todos.clear();
      expect(get(todos)).toEqual([]);
    });
  });

  describe("update", () => {
    it("can update todos with a callback", () => {
      const initial: TodoItem[] = [
        { content: "Task 1", status: "pending", activeForm: "Doing task 1" },
      ];
      todos.set(initial);
      todos.update((current) => [
        ...current,
        { content: "Task 2", status: "completed", activeForm: "Doing task 2" },
      ]);
      expect(get(todos)).toHaveLength(2);
    });
  });

  describe("initializeTodoListener", () => {
    it("listens for claude:todo-update events", async () => {
      await initializeTodoListener();

      const newTodos: TodoItem[] = [
        { content: "Backend task", status: "in_progress", activeForm: "Running backend task" },
      ];
      emitMockEvent("claude:todo-update", { todos: newTodos });

      expect(get(todos)).toEqual(newTodos);
    });

    it("does not register a duplicate listener when called twice", async () => {
      await initializeTodoListener();
      await initializeTodoListener();

      const newTodos: TodoItem[] = [
        { content: "Task", status: "pending", activeForm: "Doing task" },
      ];
      emitMockEvent("claude:todo-update", { todos: newTodos });

      // Should only have been set once (not doubled)
      expect(get(todos)).toEqual(newTodos);
    });
  });

  describe("cleanupTodoListener", () => {
    it("stops listening for events after cleanup", async () => {
      await initializeTodoListener();
      cleanupTodoListener();

      emitMockEvent("claude:todo-update", {
        todos: [{ content: "Task", status: "pending", activeForm: "Doing task" }],
      });

      // Should not have been updated since we cleaned up
      expect(get(todos)).toEqual([]);
    });

    it("is safe to call when not initialised", () => {
      expect(() => cleanupTodoListener()).not.toThrow();
    });
  });
});
