import { describe, it, expect, vi, beforeEach } from "vitest";
import { invoke } from "@tauri-apps/api/core";
import { setMockInvokeResult } from "../../../vitest.setup";
import { quickActionsStore, type QuickAction } from "./quickActions";

describe("QuickAction interface", () => {
  it("defines all required fields", () => {
    const action: QuickAction = {
      id: "action-123",
      name: "Run Tests",
      prompt: "Please run the tests",
      icon: "play",
      is_default: false,
      created_at: "2024-01-01T00:00:00Z",
      updated_at: "2024-01-01T00:00:00Z",
    };

    expect(action.id).toBe("action-123");
    expect(action.name).toBe("Run Tests");
    expect(action.prompt).toBe("Please run the tests");
    expect(action.icon).toBe("play");
    expect(action.is_default).toBe(false);
    expect(action.created_at).toBe("2024-01-01T00:00:00Z");
    expect(action.updated_at).toBe("2024-01-01T00:00:00Z");
  });

  it("supports default actions", () => {
    const defaultAction: QuickAction = {
      id: "default-review-pr",
      name: "Review PR",
      prompt: "Please review this pull request",
      icon: "git-pull-request",
      is_default: true,
      created_at: "2024-01-01T00:00:00Z",
      updated_at: "2024-01-01T00:00:00Z",
    };

    expect(defaultAction.is_default).toBe(true);
    expect(defaultAction.id).toContain("default-");
  });
});

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

  describe("store structure", () => {
    it("has all expected methods", () => {
      expect(typeof quickActionsStore.loadQuickActions).toBe("function");
      expect(typeof quickActionsStore.saveQuickAction).toBe("function");
      expect(typeof quickActionsStore.createQuickAction).toBe("function");
      expect(typeof quickActionsStore.updateQuickAction).toBe("function");
      expect(typeof quickActionsStore.deleteQuickAction).toBe("function");
      expect(typeof quickActionsStore.resetDefaults).toBe("function");
    });

    it("has subscribable stores", () => {
      expect(typeof quickActionsStore.actions.subscribe).toBe("function");
      expect(typeof quickActionsStore.isLoading.subscribe).toBe("function");
    });
  });

  describe("loadQuickActions", () => {
    it("loads quick actions from backend", async () => {
      const mockActions: QuickAction[] = [
        {
          id: "action-1",
          name: "Action 1",
          prompt: "prompt 1",
          icon: "star",
          is_default: false,
          created_at: "2024-01-01T00:00:00Z",
          updated_at: "2024-01-01T00:00:00Z",
        },
      ];

      setMockInvokeResult("list_quick_actions", mockActions);

      await quickActionsStore.loadQuickActions();

      expect(invoke).toHaveBeenCalledWith("list_quick_actions");
    });

    it("handles load errors gracefully", async () => {
      const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
      setMockInvokeResult("list_quick_actions", new Error("Failed to load"));

      await quickActionsStore.loadQuickActions();

      expect(consoleSpy).toHaveBeenCalledWith("Failed to load quick actions:", expect.any(Error));
      consoleSpy.mockRestore();
    });
  });

  describe("saveQuickAction", () => {
    it("saves action and reloads list", async () => {
      const action: QuickAction = {
        id: "action-123",
        name: "Test",
        prompt: "test prompt",
        icon: "star",
        is_default: false,
        created_at: "2024-01-01T00:00:00Z",
        updated_at: "2024-01-01T00:00:00Z",
      };

      setMockInvokeResult("save_quick_action", undefined);
      setMockInvokeResult("list_quick_actions", [action]);

      const result = await quickActionsStore.saveQuickAction(action);

      expect(result).toBe(true);
      expect(invoke).toHaveBeenCalledWith("save_quick_action", { action });
    });

    it("handles save errors gracefully", async () => {
      const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
      setMockInvokeResult("save_quick_action", new Error("Failed to save"));

      const action: QuickAction = {
        id: "action-123",
        name: "Test",
        prompt: "test prompt",
        icon: "star",
        is_default: false,
        created_at: "2024-01-01T00:00:00Z",
        updated_at: "2024-01-01T00:00:00Z",
      };

      const result = await quickActionsStore.saveQuickAction(action);

      expect(result).toBe(false);
      expect(consoleSpy).toHaveBeenCalledWith("Failed to save quick action:", expect.any(Error));
      consoleSpy.mockRestore();
    });
  });

  describe("createQuickAction", () => {
    it("creates new action with generated ID and timestamps", async () => {
      setMockInvokeResult("save_quick_action", undefined);
      setMockInvokeResult("list_quick_actions", []);

      const result = await quickActionsStore.createQuickAction("My Action", "Do something", "star");

      expect(result).toBe(true);
      expect(invoke).toHaveBeenCalledWith(
        "save_quick_action",
        expect.objectContaining({
          action: expect.objectContaining({
            name: "My Action",
            prompt: "Do something",
            icon: "star",
            is_default: false,
          }),
        })
      );
    });
  });

  describe("updateQuickAction", () => {
    it("updates existing action preserving created_at", async () => {
      const existingAction: QuickAction = {
        id: "action-123",
        name: "Old Name",
        prompt: "old prompt",
        icon: "old-icon",
        is_default: false,
        created_at: "2024-01-01T00:00:00Z",
        updated_at: "2024-01-01T00:00:00Z",
      };

      setMockInvokeResult("list_quick_actions", [existingAction]);
      setMockInvokeResult("save_quick_action", undefined);

      const result = await quickActionsStore.updateQuickAction(
        "action-123",
        "New Name",
        "new prompt",
        "new-icon"
      );

      expect(result).toBe(true);
      expect(invoke).toHaveBeenCalledWith(
        "save_quick_action",
        expect.objectContaining({
          action: expect.objectContaining({
            id: "action-123",
            name: "New Name",
            prompt: "new prompt",
            icon: "new-icon",
            created_at: "2024-01-01T00:00:00Z",
          }),
        })
      );
    });

    it("returns false for non-existent action", async () => {
      const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
      setMockInvokeResult("list_quick_actions", []);

      const result = await quickActionsStore.updateQuickAction(
        "non-existent",
        "Name",
        "prompt",
        "icon"
      );

      expect(result).toBe(false);
      expect(consoleSpy).toHaveBeenCalledWith("Quick action not found for update");
      consoleSpy.mockRestore();
    });
  });

  describe("deleteQuickAction", () => {
    it("deletes action by ID", async () => {
      setMockInvokeResult("delete_quick_action", undefined);
      setMockInvokeResult("list_quick_actions", []);

      const result = await quickActionsStore.deleteQuickAction("action-123");

      expect(result).toBe(true);
      expect(invoke).toHaveBeenCalledWith("delete_quick_action", { actionId: "action-123" });
    });

    it("handles delete errors gracefully", async () => {
      const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
      setMockInvokeResult("delete_quick_action", new Error("Cannot delete default action"));

      const result = await quickActionsStore.deleteQuickAction("default-1");

      expect(result).toBe(false);
      expect(consoleSpy).toHaveBeenCalledWith("Failed to delete quick action:", expect.any(Error));
      consoleSpy.mockRestore();
    });
  });

  describe("resetDefaults", () => {
    it("resets default actions", async () => {
      setMockInvokeResult("reset_default_quick_actions", undefined);
      setMockInvokeResult("list_quick_actions", []);

      const result = await quickActionsStore.resetDefaults();

      expect(result).toBe(true);
      expect(invoke).toHaveBeenCalledWith("reset_default_quick_actions");
    });

    it("handles reset errors gracefully", async () => {
      const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
      setMockInvokeResult("reset_default_quick_actions", new Error("Reset failed"));

      const result = await quickActionsStore.resetDefaults();

      expect(result).toBe(false);
      expect(consoleSpy).toHaveBeenCalledWith(
        "Failed to reset default quick actions:",
        expect.any(Error)
      );
      consoleSpy.mockRestore();
    });
  });
});

describe("quick action ID generation", () => {
  it("generates unique custom action IDs", () => {
    const generateId = () => `custom-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;

    const id1 = generateId();
    const id2 = generateId();

    expect(id1).toMatch(/^custom-\d+-[a-z0-9]+$/);
    expect(id2).toMatch(/^custom-\d+-[a-z0-9]+$/);
    expect(id1).not.toBe(id2);
  });
});

describe("action validation", () => {
  it("requires non-empty name", () => {
    const action = { name: "" };
    const isValid = action.name.trim().length > 0;
    expect(isValid).toBe(false);
  });

  it("requires non-empty prompt", () => {
    const action = { prompt: "   " };
    const isValid = action.prompt.trim().length > 0;
    expect(isValid).toBe(false);
  });

  it("requires non-empty icon", () => {
    const action = { icon: "star" };
    const isValid = action.icon.trim().length > 0;
    expect(isValid).toBe(true);
  });
});

describe("action icons", () => {
  it("supports various icon names", () => {
    const validIcons = [
      "git-pull-request",
      "play",
      "file-text",
      "alert-circle",
      "check-square",
      "refresh-cw",
      "star",
      "code",
      "terminal",
    ];

    validIcons.forEach((icon) => {
      expect(typeof icon).toBe("string");
      expect(icon.length).toBeGreaterThan(0);
    });
  });
});

describe("action sorting", () => {
  it("sorts default actions before custom actions", () => {
    const actions = [
      { id: "custom-1", name: "Custom", is_default: false },
      { id: "default-1", name: "Default", is_default: true },
    ];

    const sorted = [...actions].sort((a, b) => {
      const defaultCmp = (b.is_default ? 1 : 0) - (a.is_default ? 1 : 0);
      if (defaultCmp !== 0) return defaultCmp;
      return a.name.localeCompare(b.name);
    });

    expect(sorted[0].is_default).toBe(true);
    expect(sorted[1].is_default).toBe(false);
  });

  it("sorts alphabetically within same default status", () => {
    const actions = [
      { id: "default-2", name: "Zebra", is_default: true },
      { id: "default-1", name: "Apple", is_default: true },
    ];

    const sorted = [...actions].sort((a, b) => {
      const defaultCmp = (b.is_default ? 1 : 0) - (a.is_default ? 1 : 0);
      if (defaultCmp !== 0) return defaultCmp;
      return a.name.localeCompare(b.name);
    });

    expect(sorted[0].name).toBe("Apple");
    expect(sorted[1].name).toBe("Zebra");
  });
});
