/**
 * Autoplay API tests
 */

import { describe, it, expect, beforeEach, vi } from "vitest";
import {
  getAutoplaySettings,
  setAutoplaySettings,
  cancelAutoplayCountdown,
  playNextEpisode,
  type AutoplaySettings,
} from "./autoplay";
import type { PlayItemRequest } from "./bindings";

vi.mock("@tauri-apps/api/core", () => ({
  invoke: vi.fn(async (command: string, args?: any) => {
    if (command === "player_get_autoplay_settings") {
      return {
        enabled: true,
        countdownSeconds: 10,
        maxEpisodes: 5,
      };
    }
    if (command === "player_set_autoplay_settings") {
      return args.settings;
    }
    if (command === "player_cancel_autoplay_countdown") {
      return undefined;
    }
    if (command === "player_play_next_episode") {
      return undefined;
    }
    return null;
  }),
}));

// setAutoplaySettings sources the user id from the auth store
vi.mock("$lib/stores/auth", () => ({
  auth: { getUserId: () => "user-1" },
}));

// Minimal valid PlayItemRequest for playNextEpisode tests
function makeItem(overrides: Partial<PlayItemRequest> = {}): PlayItemRequest {
  return {
    id: "item-123",
    title: "Episode 1",
    streamUrl: "http://example/stream",
    videoCodec: "h264",
    needsTranscoding: false,
    ...overrides,
  };
}

describe("autoplay API", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe("getAutoplaySettings", () => {
    it("should fetch autoplay settings", async () => {
      const settings = await getAutoplaySettings();
      expect(settings).toHaveProperty("enabled");
      expect(settings).toHaveProperty("countdownSeconds");
      expect(typeof settings.enabled).toBe("boolean");
      expect(typeof settings.countdownSeconds).toBe("number");
    });

    it("should invoke correct backend command", async () => {
      const { invoke } = await import("@tauri-apps/api/core");
      const invokeSpy = vi.mocked(invoke);

      await getAutoplaySettings();

      expect(invokeSpy).toHaveBeenCalledWith("player_get_autoplay_settings");
    });
  });

  describe("setAutoplaySettings", () => {
    it("should set autoplay settings with enabled true", async () => {
      const settings: AutoplaySettings = {
        enabled: true,
        countdownSeconds: 15,
        maxEpisodes: 5,
      };

      const result = await setAutoplaySettings(settings);

      expect(result).toEqual(settings);
    });

    it("should set autoplay settings with enabled false", async () => {
      const settings: AutoplaySettings = {
        enabled: false,
        countdownSeconds: 10,
        maxEpisodes: 5,
      };

      const result = await setAutoplaySettings(settings);

      expect(result.enabled).toBe(false);
    });

    it("should invoke correct backend command with settings", async () => {
      const { invoke } = await import("@tauri-apps/api/core");
      const invokeSpy = vi.mocked(invoke);

      const settings: AutoplaySettings = {
        enabled: true,
        countdownSeconds: 20,
        maxEpisodes: 5,
      };

      await setAutoplaySettings(settings);

      const call = invokeSpy.mock.calls.find(
        (c) => c[0] === "player_set_autoplay_settings"
      );
      expect(call).toBeDefined();
      expect(call![1]).toEqual({ userId: "user-1", settings });
    });

    it("should support different countdown values", async () => {
      const countdownValues = [5, 10, 15, 30];

      for (const countdown of countdownValues) {
        const settings: AutoplaySettings = {
          enabled: true,
          countdownSeconds: countdown,
          maxEpisodes: 5,
        };

        const result = await setAutoplaySettings(settings);
        expect(result.countdownSeconds).toBe(countdown);
      }
    });
  });

  describe("cancelAutoplayCountdown", () => {
    it("should cancel autoplay countdown", async () => {
      await cancelAutoplayCountdown();

      const { invoke } = await import("@tauri-apps/api/core");
      const invokeSpy = vi.mocked(invoke);

      expect(invokeSpy).toHaveBeenCalledWith("player_cancel_autoplay_countdown");
    });
  });

  describe("playNextEpisode", () => {
    it("should play next episode with item", async () => {
      const mockItem = makeItem();

      await playNextEpisode(mockItem);

      const { invoke } = await import("@tauri-apps/api/core");
      const invokeSpy = vi.mocked(invoke);

      const call = invokeSpy.mock.calls.find(
        (c) => c[0] === "player_play_next_episode"
      );
      expect(call).toBeDefined();
      expect(call![1]).toEqual({ item: mockItem });
    });

    it("should handle different item types", async () => {
      const items = [
        makeItem({ id: "1", title: "Episode 1" }),
        makeItem({ id: "2", title: "Episode 2" }),
        makeItem({ id: "3", title: "Episode 3" }),
      ];

      for (const item of items) {
        await expect(playNextEpisode(item)).resolves.toBeUndefined();
      }
    });
  });

  describe("autoplay settings structure", () => {
    it("should have enabled boolean property", async () => {
      const settings = await getAutoplaySettings();
      expect(typeof settings.enabled).toBe("boolean");
    });

    it("should have countdownSeconds number property", async () => {
      const settings = await getAutoplaySettings();
      expect(typeof settings.countdownSeconds).toBe("number");
      expect(settings.countdownSeconds).toBeGreaterThan(0);
    });
  });
});
