import { describe, it, expect, beforeEach, vi } from "vitest";
import { Test, TestingModule } from "@nestjs/testing";
import { StatsService } from "./stats.service";
import { PrismaService } from "../../prisma/prisma.service";
import { EntryStatus } from "@prisma/client";

describe("StatsService", () => {
  let service: StatsService;
  let prisma: PrismaService;

  const mockPrismaService = {
    knowledgeEntry: {
      count: vi.fn(),
      findMany: vi.fn(),
    },
    knowledgeTag: {
      count: vi.fn(),
      findMany: vi.fn(),
    },
    knowledgeLink: {
      count: vi.fn(),
    },
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        StatsService,
        {
          provide: PrismaService,
          useValue: mockPrismaService,
        },
      ],
    }).compile();

    service = module.get<StatsService>(StatsService);
    prisma = module.get<PrismaService>(PrismaService);

    vi.clearAllMocks();
  });

  it("should be defined", () => {
    expect(service).toBeDefined();
  });

  describe("getStats", () => {
    it("should return knowledge base statistics", async () => {
      // Mock all the parallel queries
      mockPrismaService.knowledgeEntry.count
        .mockResolvedValueOnce(10) // total entries
        .mockResolvedValueOnce(5) // published
        .mockResolvedValueOnce(3) // drafts
        .mockResolvedValueOnce(2); // archived

      mockPrismaService.knowledgeTag.count.mockResolvedValue(7);
      mockPrismaService.knowledgeLink.count.mockResolvedValue(15);

      mockPrismaService.knowledgeEntry.findMany
        .mockResolvedValueOnce([
          // most connected
          {
            id: "entry-1",
            slug: "test-entry",
            title: "Test Entry",
            _count: { incomingLinks: 5, outgoingLinks: 3 },
          },
        ])
        .mockResolvedValueOnce([
          // recent activity
          {
            id: "entry-2",
            slug: "recent-entry",
            title: "Recent Entry",
            updatedAt: new Date(),
            status: EntryStatus.PUBLISHED,
          },
        ]);

      mockPrismaService.knowledgeTag.findMany.mockResolvedValue([
        {
          id: "tag-1",
          name: "Test Tag",
          slug: "test-tag",
          color: "#FF0000",
          _count: { entries: 3 },
        },
      ]);

      const result = await service.getStats("workspace-1");

      expect(result.overview.totalEntries).toBe(10);
      expect(result.overview.totalTags).toBe(7);
      expect(result.overview.totalLinks).toBe(15);
      expect(result.overview.publishedEntries).toBe(5);
      expect(result.overview.draftEntries).toBe(3);
      expect(result.overview.archivedEntries).toBe(2);

      expect(result.mostConnected).toHaveLength(1);
      expect(result.mostConnected[0].totalConnections).toBe(8);

      expect(result.recentActivity).toHaveLength(1);
      expect(result.tagDistribution).toHaveLength(1);
    });

    it("should handle empty knowledge base", async () => {
      // Mock all counts as 0
      mockPrismaService.knowledgeEntry.count.mockResolvedValue(0);
      mockPrismaService.knowledgeTag.count.mockResolvedValue(0);
      mockPrismaService.knowledgeLink.count.mockResolvedValue(0);
      mockPrismaService.knowledgeEntry.findMany.mockResolvedValue([]);
      mockPrismaService.knowledgeTag.findMany.mockResolvedValue([]);

      const result = await service.getStats("workspace-1");

      expect(result.overview.totalEntries).toBe(0);
      expect(result.overview.totalTags).toBe(0);
      expect(result.overview.totalLinks).toBe(0);
      expect(result.mostConnected).toHaveLength(0);
      expect(result.recentActivity).toHaveLength(0);
      expect(result.tagDistribution).toHaveLength(0);
    });
  });
});
