import { describe, it, expect, vi, beforeEach } from 'vitest';
import { NextRequest } from 'next/server';

// Mock rate limiting - must be before route import
vi.mock('@/lib/rate-limit', () => ({
  withRateLimit: vi.fn().mockResolvedValue({ allowed: true, remaining: 100, limit: 120, resetAt: Date.now() + 60000 }),
  createRateLimitResponse: vi.fn(),
  createRateLimitHeaders: vi.fn().mockReturnValue({}),
}));

// Mock cache - must be before route import
vi.mock('@/lib/cache', () => ({
  getCached: vi.fn().mockResolvedValue(null),
  setCache: vi.fn().mockResolvedValue(undefined),
  cacheKeys: { stats: () => 'stats' },
  cacheTTL: { stats: 3600 },
}));

// Mock the db module - must be before imports that use it
vi.mock('@skillhub/db', () => {
  const mockStatsRow = [{ totalSkills: 100, totalContributors: 50 }];
  const mockDownloadsRow = [{ totalDownloads: 5000 }];
  const mockCategoryRow = [{ count: 8 }];
  return {
    createDb: vi.fn(() => ({
      select: vi.fn().mockReturnValue({
        from: vi.fn((table: unknown) => {
          // categories table query returns count directly (no .where())
          if (table === 'categories-table') {
            return Promise.resolve(mockCategoryRow);
          }
          // skills table: thenable for downloads (no .where()) + .where() for filtered stats
          return {
            where: vi.fn().mockResolvedValue(mockStatsRow),
            then: (resolve: (v: unknown) => void, reject: (e: unknown) => void) =>
              Promise.resolve(mockDownloadsRow).then(resolve, reject),
          };
        }),
      }),
    })),
    skills: { downloadCount: 'download_count', githubOwner: 'github_owner', isDuplicate: 'is_duplicate', skillType: 'skill_type' },
    categories: 'categories-table',
    sql: vi.fn((..._args: unknown[]) => 'mock-sql'),
  };
});

import { GET } from './route';

// Helper to create mock request
function createMockRequest(url = 'http://localhost:3000/api/stats') {
  return new NextRequest(url);
}

describe('GET /api/stats', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should return totalSkills count', async () => {
    const request = createMockRequest();
    const response = await GET(request);
    const data = await response.json();

    expect(response.status).toBe(200);
    expect(data.totalSkills).toBeDefined();
    expect(typeof data.totalSkills).toBe('number');
  });

  it('should return totalDownloads sum', async () => {
    const request = createMockRequest();
    const response = await GET(request);
    const data = await response.json();

    expect(data.totalDownloads).toBeDefined();
    expect(typeof data.totalDownloads).toBe('number');
  });

  it('should return totalCategories count', async () => {
    const request = createMockRequest();
    const response = await GET(request);
    const data = await response.json();

    expect(data.totalCategories).toBeDefined();
    expect(typeof data.totalCategories).toBe('number');
  });

  it('should return totalContributors count', async () => {
    const request = createMockRequest();
    const response = await GET(request);
    const data = await response.json();

    expect(data.totalContributors).toBeDefined();
    expect(typeof data.totalContributors).toBe('number');
  });

  it('should return platforms count', async () => {
    const request = createMockRequest();
    const response = await GET(request);
    const data = await response.json();

    expect(data.platforms).toBe(5);
  });
});
