import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { AgentMessagesService } from "./agent-messages.service";
import { PrismaService } from "../../prisma/prisma.service";

describe("AgentMessagesService", () => {
  let service: AgentMessagesService;
  let prisma: {
    agentConversationMessage: {
      findMany: ReturnType<typeof vi.fn>;
      count: ReturnType<typeof vi.fn>;
    };
  };

  beforeEach(() => {
    prisma = {
      agentConversationMessage: {
        findMany: vi.fn(),
        count: vi.fn(),
      },
    };

    service = new AgentMessagesService(prisma as unknown as PrismaService);
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  describe("getMessages", () => {
    it("returns paginated messages from Prisma", async () => {
      const sessionId = "agent-123";
      const messages = [
        {
          id: "msg-1",
          sessionId,
          provider: "internal",
          role: "assistant",
          content: "First message",
          timestamp: new Date("2026-03-07T16:00:00.000Z"),
          metadata: {},
        },
        {
          id: "msg-2",
          sessionId,
          provider: "internal",
          role: "user",
          content: "Second message",
          timestamp: new Date("2026-03-07T15:59:00.000Z"),
          metadata: {},
        },
      ];

      prisma.agentConversationMessage.findMany.mockResolvedValue(messages);
      prisma.agentConversationMessage.count.mockResolvedValue(2);

      const result = await service.getMessages(sessionId, 50, 0);

      expect(prisma.agentConversationMessage.findMany).toHaveBeenCalledWith({
        where: { sessionId },
        orderBy: { timestamp: "desc" },
        take: 50,
        skip: 0,
      });
      expect(prisma.agentConversationMessage.count).toHaveBeenCalledWith({ where: { sessionId } });
      expect(result).toEqual({
        messages,
        total: 2,
      });
    });

    it("applies limit and cursor (skip) correctly", async () => {
      const sessionId = "agent-456";
      const limit = 10;
      const cursor = 20;

      prisma.agentConversationMessage.findMany.mockResolvedValue([]);
      prisma.agentConversationMessage.count.mockResolvedValue(42);

      await service.getMessages(sessionId, limit, cursor);

      expect(prisma.agentConversationMessage.findMany).toHaveBeenCalledWith({
        where: { sessionId },
        orderBy: { timestamp: "desc" },
        take: limit,
        skip: cursor,
      });
    });

    it("returns empty messages array when no messages exist", async () => {
      const sessionId = "agent-empty";

      prisma.agentConversationMessage.findMany.mockResolvedValue([]);
      prisma.agentConversationMessage.count.mockResolvedValue(0);

      const result = await service.getMessages(sessionId, 25, 0);

      expect(result).toEqual({
        messages: [],
        total: 0,
      });
    });
  });
});
