/**
 * Queue store tests
 *
 * TRACES: UR-005, UR-015 | DR-005, DR-020
 */

import { describe, it, expect, beforeEach, vi } from "vitest";
import { queue, currentQueueItem, queueItems } from "./queue";
import { get } from "svelte/store";

vi.mock("@tauri-apps/api/core", () => ({
  invoke: vi.fn(async (command) => {
    if (command === "player_get_queue") {
      return {
        items: [],
        currentIndex: null,
        shuffle: false,
        repeat: "off",
        hasNext: false,
        hasPrevious: false,
      };
    }
    return null;
  }),
}));

vi.mock("@tauri-apps/api/event", () => ({
  listen: vi.fn(async () => () => {}),
}));

describe("queue store", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe("queue state structure", () => {
    it("should have items array", () => {
      const state = get(queue);
      expect(state).toHaveProperty("items");
      expect(Array.isArray(state.items)).toBe(true);
    });

    it("should track current index", () => {
      const state = get(queue);
      expect(state).toHaveProperty("currentIndex");
    });

    it("should track shuffle state", () => {
      const state = get(queue);
      expect(state).toHaveProperty("shuffle");
      expect(typeof state.shuffle).toBe("boolean");
    });

    it("should track repeat mode", () => {
      const state = get(queue);
      expect(state).toHaveProperty("repeat");
      expect(["off", "all", "one"]).toContain(state.repeat);
    });

    it("should track navigation state", () => {
      const state = get(queue);
      expect(state).toHaveProperty("hasNext");
      expect(state).toHaveProperty("hasPrevious");
      expect(typeof state.hasNext).toBe("boolean");
      expect(typeof state.hasPrevious).toBe("boolean");
    });
  });

  describe("derived stores", () => {
    it("should provide currentQueueItem derived store", () => {
      const current = get(currentQueueItem);
      expect(current).toBeDefined();
    });

    it("should provide queueItems derived store", () => {
      const items = get(queueItems);
      expect(Array.isArray(items)).toBe(true);
    });
  });

  describe("subscription", () => {
    it("should allow subscriptions to queue changes", () => {
      const states: any[] = [];
      const unsubscribe = queue.subscribe((state) => {
        states.push(state);
      });

      expect(states.length).toBeGreaterThan(0);
      unsubscribe();
    });

    it("should notify multiple subscribers", () => {
      const states1: any[] = [];
      const states2: any[] = [];

      const unsub1 = queue.subscribe((state) => states1.push(state));
      const unsub2 = queue.subscribe((state) => states2.push(state));

      expect(states1.length).toBe(states2.length);

      unsub1();
      unsub2();
    });
  });

  describe("initial state", () => {
    it("should start with empty queue", () => {
      const state = get(queue);
      expect(state.items.length).toBe(0);
    });

    it("should start with no current track", () => {
      const state = get(queue);
      expect(state.currentIndex).toBeNull();
    });

    it("should start with shuffle off", () => {
      const state = get(queue);
      expect(state.shuffle).toBe(false);
    });

    it("should start with repeat off", () => {
      const state = get(queue);
      expect(state.repeat).toBe("off");
    });
  });

  describe("queue operations", () => {
    it("should support clearing queue", () => {
      if (typeof (queue as any).clear === "function") {
        (queue as any).clear?.();
        const state = get(queue);
        expect(state.items.length).toBe(0);
      }
    });

    it("should support adding items to queue", () => {
      if (typeof (queue as any).addItem === "function") {
        const mockItem = { id: "test-1", name: "Test Track" };
        (queue as any).addItem?.(mockItem);
        const state = get(queue);
        expect(state.items.length).toBeGreaterThanOrEqual(0);
      }
    });
  });

  describe("repeat modes", () => {
    it("should support off repeat mode", () => {
      const state = get(queue);
      expect(["off", "all", "one"]).toContain(state.repeat);
    });

    it("should cycle through repeat modes", () => {
      const state = get(queue);
      const validModes = ["off", "all", "one"];
      expect(validModes).toContain(state.repeat);
    });
  });

  describe("shuffle", () => {
    it("should track shuffle state", () => {
      const state = get(queue);
      expect(typeof state.shuffle).toBe("boolean");
    });

    it("should toggle shuffle if method exists", () => {
      if (typeof (queue as any).toggleShuffle === "function") {
        const before = get(queue).shuffle;
        (queue as any).toggleShuffle?.();
        const after = get(queue).shuffle;
        expect(typeof after).toBe("boolean");
      }
    });
  });
});
