/**
 * Federation Queries API Client Tests
 */

import { describe, it, expect, vi, beforeEach } from "vitest";
import {
  sendFederatedQuery,
  fetchQueryMessages,
  fetchQueryMessage,
  FederationMessageStatus,
} from "./federation-queries";
import * as client from "./client";

// Mock the API client
vi.mock("./client", () => ({
  apiGet: vi.fn(),
  apiPost: vi.fn(),
}));

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

  describe("sendFederatedQuery", () => {
    it("should send a query to a remote instance", async () => {
      const mockResponse = {
        id: "msg-123",
        messageId: "uuid-123",
        connectionId: "conn-1",
        query: "tasks.list",
        status: FederationMessageStatus.PENDING,
        createdAt: new Date().toISOString(),
      };

      vi.mocked(client.apiPost).mockResolvedValue(mockResponse);

      const result = await sendFederatedQuery("conn-1", "tasks.list", { limit: 10 });

      expect(client.apiPost).toHaveBeenCalledWith("/api/v1/federation/query", {
        connectionId: "conn-1",
        query: "tasks.list",
        context: { limit: 10 },
      });
      expect(result).toEqual(mockResponse);
    });

    it("should send a query without context", async () => {
      const mockResponse = {
        id: "msg-124",
        messageId: "uuid-124",
        connectionId: "conn-2",
        query: "events.today",
        status: FederationMessageStatus.PENDING,
        createdAt: new Date().toISOString(),
      };

      vi.mocked(client.apiPost).mockResolvedValue(mockResponse);

      const result = await sendFederatedQuery("conn-2", "events.today");

      expect(client.apiPost).toHaveBeenCalledWith("/api/v1/federation/query", {
        connectionId: "conn-2",
        query: "events.today",
      });
      expect(result).toEqual(mockResponse);
    });

    it("should handle API errors", async () => {
      vi.mocked(client.apiPost).mockRejectedValue(new Error("Network error"));

      await expect(sendFederatedQuery("conn-1", "tasks.list")).rejects.toThrow("Network error");
    });
  });

  describe("fetchQueryMessages", () => {
    it("should fetch all query messages", async () => {
      const mockMessages = [
        {
          id: "msg-1",
          messageId: "uuid-1",
          connectionId: "conn-1",
          query: "tasks.list",
          status: FederationMessageStatus.DELIVERED,
          response: { data: [] },
          createdAt: new Date().toISOString(),
        },
        {
          id: "msg-2",
          messageId: "uuid-2",
          connectionId: "conn-2",
          query: "events.list",
          status: FederationMessageStatus.PENDING,
          createdAt: new Date().toISOString(),
        },
      ];

      vi.mocked(client.apiGet).mockResolvedValue(mockMessages);

      const result = await fetchQueryMessages();

      expect(client.apiGet).toHaveBeenCalledWith("/api/v1/federation/queries");
      expect(result).toEqual(mockMessages);
    });

    it("should fetch query messages filtered by status", async () => {
      const mockMessages = [
        {
          id: "msg-1",
          messageId: "uuid-1",
          connectionId: "conn-1",
          query: "tasks.list",
          status: FederationMessageStatus.DELIVERED,
          response: { data: [] },
          createdAt: new Date().toISOString(),
        },
      ];

      vi.mocked(client.apiGet).mockResolvedValue(mockMessages);

      const result = await fetchQueryMessages(FederationMessageStatus.DELIVERED);

      expect(client.apiGet).toHaveBeenCalledWith("/api/v1/federation/queries?status=DELIVERED");
      expect(result).toEqual(mockMessages);
    });
  });

  describe("fetchQueryMessage", () => {
    it("should fetch a single query message", async () => {
      const mockMessage = {
        id: "msg-123",
        messageId: "uuid-123",
        connectionId: "conn-1",
        query: "tasks.list",
        status: FederationMessageStatus.DELIVERED,
        response: { data: [{ id: "task-1", title: "Test Task" }] },
        createdAt: new Date().toISOString(),
      };

      vi.mocked(client.apiGet).mockResolvedValue(mockMessage);

      const result = await fetchQueryMessage("msg-123");

      expect(client.apiGet).toHaveBeenCalledWith("/api/v1/federation/queries/msg-123");
      expect(result).toEqual(mockMessage);
    });

    it("should handle not found errors", async () => {
      vi.mocked(client.apiGet).mockRejectedValue(new Error("Not found"));

      await expect(fetchQueryMessage("msg-999")).rejects.toThrow("Not found");
    });
  });
});
