// src/services/db/price.db.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { mockPoolInstance } from '../../tests/setup/tests-setup-unit';
import { getPool } from './connection.db';
import { priceRepo } from './price.db';
import type { PriceHistoryData } from '../../types';

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

// Mock dependencies
vi.mock('./connection.db', () => ({
  getPool: vi.fn(),
}));

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('Price DB Service', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    // Make getPool return our mock instance for each test
    vi.mocked(getPool).mockReturnValue(mockPoolInstance as any);
  });

  describe('getPriceHistory', () => {
    it('should return an empty array if masterItemIds is empty and not query the db', async () => {
      const result = await priceRepo.getPriceHistory([], mockLogger);
      expect(result).toEqual([]);
      expect(mockPoolInstance.query).not.toHaveBeenCalled();
    });

    it('should execute the correct query with default limit and offset', async () => {
      mockPoolInstance.query.mockResolvedValue({ rows: [] });
      await priceRepo.getPriceHistory([1, 2], mockLogger);
      expect(mockPoolInstance.query).toHaveBeenCalledWith(
        expect.stringContaining('LIMIT $2 OFFSET $3'),
        [[1, 2], 1000, 0],
      );
    });

    it('should execute the correct query with provided limit and offset', async () => {
      mockPoolInstance.query.mockResolvedValue({ rows: [] });
      await priceRepo.getPriceHistory([1, 2], mockLogger, 50, 10);
      expect(mockPoolInstance.query).toHaveBeenCalledWith(
        expect.stringContaining('LIMIT $2 OFFSET $3'),
        [[1, 2], 50, 10],
      );
    });

    it('should return price history data on success', async () => {
      const mockHistory: PriceHistoryData[] = [
        { master_item_id: 1, price_in_cents: 199, date: '2024-01-01' },
        { master_item_id: 1, price_in_cents: 209, date: '2024-01-08' },
      ];
      mockPoolInstance.query.mockResolvedValue({ rows: mockHistory });

      const result = await priceRepo.getPriceHistory([1], mockLogger);
      expect(result).toEqual(mockHistory);
    });

    it('should log the result count on success', async () => {
      const mockHistory: PriceHistoryData[] = [
        { master_item_id: 1, price_in_cents: 199, date: '2024-01-01' },
      ];
      mockPoolInstance.query.mockResolvedValue({ rows: mockHistory });

      await priceRepo.getPriceHistory([1], mockLogger, 50, 10);
      expect(mockLogger.debug).toHaveBeenCalledWith(
        { count: 1, itemIds: 1, limit: 50, offset: 10 },
        'Fetched price history from database.',
      );
    });

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

      await expect(priceRepo.getPriceHistory([1], mockLogger, 50, 10)).rejects.toThrow(
        'Failed to retrieve price history.',
      );
      expect(mockLogger.error).toHaveBeenCalledWith(
        { err: dbError, masterItemIds: [1], limit: 50, offset: 10 },
        'Database error in getPriceHistory',
      );
    });
  });
});