// src/services/db/deals.db.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { mockPoolInstance } from '../../tests/setup/tests-setup-unit';
import { DealsRepository } from './deals.db';
import type { WatchedItemDeal } from '../../types';
import type { Pool } from 'pg';

// Un-mock the module we are testing to ensure we use the real implementation.
vi.unmock('./deals.db');

// Mock the logger to prevent console output during tests
vi.mock('../logger.server', () => ({
  logger: {
    info: vi.fn(),
    warn: vi.fn(),
    error: vi.fn(),
    debug: vi.fn(),
  },
}));
import { logger as mockLogger } from '../logger.server';

describe('Deals DB Service', () => {
  // Import the Pool type to use for casting the mock instance.
  let dealsRepo: DealsRepository;

  beforeEach(() => {
    vi.clearAllMocks();
    // Instantiate the repository with the mock pool for each test
    dealsRepo = new DealsRepository(mockPoolInstance as unknown as Pool);
  });

  describe('findBestPricesForWatchedItems', () => {
    it('should execute the correct query and return deals', async () => {
      // Arrange
      const mockDeals: WatchedItemDeal[] = [
        { master_item_id: 1, item_name: 'Apples', best_price_in_cents: 199, store_name: 'Good Food', flyer_id: 10, valid_to: '2025-12-25' },
        { master_item_id: 2, item_name: 'Milk', best_price_in_cents: 350, store_name: 'Super Grocer', flyer_id: 11, valid_to: '2025-12-24' },
      ];
      mockPoolInstance.query.mockResolvedValue({ rows: mockDeals });

      // Act
      const result = await dealsRepo.findBestPricesForWatchedItems('user-123', mockLogger);

      // Assert
      expect(result).toEqual(mockDeals);
      expect(mockPoolInstance.query).toHaveBeenCalledWith(expect.stringContaining('FROM flyer_items fi'), ['user-123']);
      expect(mockLogger.debug).toHaveBeenCalledWith({ userId: 'user-123' }, 'Finding best prices for watched items.');
    });

    it('should return an empty array if no deals are found', async () => {
      mockPoolInstance.query.mockResolvedValue({ rows: [] });

      const result = await dealsRepo.findBestPricesForWatchedItems('user-with-no-deals', mockLogger);

      expect(result).toEqual([]);
    });

    it('should re-throw the error if the database query fails', async () => {
      const dbError = new Error('DB Connection Error');
      mockPoolInstance.query.mockRejectedValue(dbError);

      await expect(dealsRepo.findBestPricesForWatchedItems('user-1', mockLogger)).rejects.toThrow(dbError);
      expect(mockLogger.error).toHaveBeenCalledWith({ err: dbError }, 'Database error in findBestPricesForWatchedItems');
    });
  });
});