import { describe, it, expect, vi, beforeEach } from "vitest";
import axios from "axios";
import { getWorkspaces, selectWorkspace } from "./workspaceUtils";
import { select } from "@inquirer/prompts";
import { ResolvedEmbeddableConfig } from "./defineConfig";
import { Ora } from "ora";
vi.mock("axios");

vi.mock("@inquirer/prompts", () => ({
  select: vi.fn(),
}));

describe("workspaceUtils", () => {
  describe("getWorkspaces", () => {
    it("should fetch workspaces and filter out dev workspaces", async () => {
      const ctx = { pushBaseUrl: "http://example.com" };
      const token = "test-token";
      const workspaceSpinner = { fail: vi.fn() };

      const workspaces = [
        { name: "Workspace 1", workspaceId: "1", devWorkspace: false },
        { name: "Workspace 2", workspaceId: "2", devWorkspace: true },
      ];

      (axios.get as any).mockResolvedValue({ data: workspaces });

      const result = await getWorkspaces(
        ctx as ResolvedEmbeddableConfig,
        token,
        workspaceSpinner as unknown as Ora,
      );

      expect(result).toEqual([
        { name: "Workspace 1", workspaceId: "1", devWorkspace: false },
      ]);
    });

    it("should handle unauthorized error", async () => {
      const ctx = { pushBaseUrl: "http://example.com" };
      const token = "test-token";
      const workspaceSpinner = { fail: vi.fn() } as unknown as Ora;

      (axios.get as any).mockRejectedValue({ response: { status: 401 } });

      await expect(
        getWorkspaces(ctx as ResolvedEmbeddableConfig, token, workspaceSpinner),
      ).rejects.toThrow();
      expect(workspaceSpinner.fail).toHaveBeenCalledWith(
        'Unauthorized. Please login using "embeddable login" command.',
      );
    });

    it("should handle other errors", async () => {
      const ctx = { pushBaseUrl: "http://example.com" };
      const token = "test-token";
      const workspaceSpinner = { fail: vi.fn() } as unknown as Ora;

      (axios.get as any).mockRejectedValue({ response: { status: 500 } });

      await expect(
        getWorkspaces(ctx as ResolvedEmbeddableConfig, token, workspaceSpinner),
      ).rejects.toThrow();
      expect(workspaceSpinner.fail).toHaveBeenCalledWith(
        "Failed to fetch workspaces",
      );
    });
  });

  describe("selectWorkspace", () => {
    beforeEach(() => {
      vi.mocked(select).mockResolvedValue({
        name: "Workspace 2",
        workspaceId: "2",
        devWorkspace: false,
      });
    });

    it("should select a workspace when only one is available", async () => {
      const ora = vi.fn().mockReturnValue({
        start: vi.fn().mockReturnThis(),
        fail: vi.fn(),
        info: vi.fn(),
        succeed: vi.fn(),
      });

      const ctx = { pushBaseUrl: "http://example.com" };
      const token = "test-token";

      const workspaces = [
        { name: "Workspace 1", workspaceId: "1", devWorkspace: false },
      ];

      (axios.get as any).mockResolvedValue({ data: workspaces });

      const selectedWorkspace = await selectWorkspace(
        ora,
        ctx as ResolvedEmbeddableConfig,
        token,
      );

      expect(selectedWorkspace).toEqual(workspaces[0]);
      expect(ora().succeed).toHaveBeenCalledWith(`Workspace: Workspace 1 (1)`);
    });

    it("should prompt user to select a workspace when multiple are available", async () => {
      const ora = vi.fn().mockReturnValue({
        start: vi.fn().mockReturnThis(),
        fail: vi.fn(),
        info: vi.fn(),
        succeed: vi.fn(),
      });
      const ctx = { pushBaseUrl: "http://example.com" };
      const token = "test-token";

      const workspaces = [
        { name: "Workspace 1", workspaceId: "1", devWorkspace: false },
        { name: "Workspace 2", workspaceId: "2", devWorkspace: false },
      ];

      (axios.get as any).mockResolvedValue({ data: workspaces });

      const selectedWorkspace = await selectWorkspace(
        ora,
        ctx as ResolvedEmbeddableConfig,
        token,
      );

      expect(selectedWorkspace).toEqual(workspaces[1]);
      expect(ora().succeed).toHaveBeenCalledWith(`Workspace: Workspace 2 (2)`);
    });

    it("should handle no workspaces found", async () => {
      const ora = vi.fn().mockReturnValue({
        start: vi.fn().mockReturnThis(),
        fail: vi.fn(),
        info: vi.fn(),
        succeed: vi.fn(),
      });
      const ctx = { pushBaseUrl: "http://example.com" };
      const token = "test-token";

      (axios.get as any).mockResolvedValue({ data: [] });

      await expect(
        selectWorkspace(ora, ctx as ResolvedEmbeddableConfig, token),
      ).rejects.toThrow();
      expect(ora().fail).toHaveBeenCalledWith("No workspaces found");
    });
  });
});
