// src/routes/stats.routes.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import supertest from 'supertest';
import statsRouter from './stats.routes';
import { mockLogger } from '../tests/utils/mockLogger';
import { createTestApp } from '../tests/utils/createTestApp';

// 1. Mock the Service Layer directly.
vi.mock('../services/db/index.db', () => ({
  adminRepo: {
    getMostFrequentSaleItems: vi.fn(),
  },
}));

// Mock the logger to keep test output clean
vi.mock('../services/logger.server', () => ({
  logger: mockLogger,
}));

// Import the mocked db module to control its functions in tests
import * as db from '../services/db/index.db';

const expectLogger = expect.objectContaining({
  info: expect.any(Function),
  error: expect.any(Function),
});

describe('Stats Routes (/api/stats)', () => {
  const app = createTestApp({ router: statsRouter, basePath: '/api/stats' });

  // Add a basic error handler to capture errors passed to next(err) and return JSON.
  // This prevents unhandled error crashes in tests and ensures we get the 500 response we expect.
  app.use((err: any, req: any, res: any, next: any) => {
    res.status(err.status || 500).json({ message: err.message, errors: err.errors });
  });

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

  describe('GET /most-frequent-sales', () => {
    it('should return most frequent sale items with default parameters', async () => {
      vi.mocked(db.adminRepo.getMostFrequentSaleItems).mockResolvedValue([]);
      const response = await supertest(app).get('/api/stats/most-frequent-sales');
      expect(response.status).toBe(200);
      expect(db.adminRepo.getMostFrequentSaleItems).toHaveBeenCalledWith(30, 10, expectLogger);
    });

    it('should use provided query parameters', async () => {
      vi.mocked(db.adminRepo.getMostFrequentSaleItems).mockResolvedValue([]);
      await supertest(app).get('/api/stats/most-frequent-sales?days=90&limit=5');
      expect(db.adminRepo.getMostFrequentSaleItems).toHaveBeenCalledWith(90, 5, expectLogger);
    });

    it('should return 500 if the database call fails', async () => {
      vi.mocked(db.adminRepo.getMostFrequentSaleItems).mockRejectedValue(new Error('DB Error'));
      const response = await supertest(app).get('/api/stats/most-frequent-sales');
      expect(response.status).toBe(500);
      expect(response.body.message).toBe('DB Error');
    });

    it('should return 400 for invalid query parameters', async () => {
      const response = await supertest(app).get('/api/stats/most-frequent-sales?days=0&limit=abc');
      expect(response.status).toBe(400);
      expect(response.body.errors).toBeDefined();
      expect(response.body.errors.length).toBe(2);
    });
  });
});