// src/services/flyerDataTransformer.test.ts
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { FlyerDataTransformer } from './flyerDataTransformer';
import { logger as mockLogger } from './logger.server';
import { generateFlyerIcon } from '../utils/imageProcessor';
import type { z } from 'zod';
import type { AiFlyerDataSchema } from './flyerProcessingService.server';
import type { FlyerItemInsert } from '../types';

// Mock the dependencies
vi.mock('../utils/imageProcessor', () => ({
  generateFlyerIcon: vi.fn(),
}));

vi.mock('./logger.server', () => ({
  logger: { info: vi.fn(), error: vi.fn(), warn: vi.fn(), debug: vi.fn() }
}));

describe('FlyerDataTransformer', () => {
  let transformer: FlyerDataTransformer;

  beforeEach(() => {
    vi.clearAllMocks();
    transformer = new FlyerDataTransformer();

    // Provide a default mock implementation for generateFlyerIcon
    vi.mocked(generateFlyerIcon).mockResolvedValue('icon-flyer-page-1.webp');
  });

  it('should transform AI data into database-ready format with a user ID', async () => {
    // Arrange
    const extractedData: z.infer<typeof AiFlyerDataSchema> = {
      store_name: 'Test Store',
      valid_from: '2024-01-01',
      valid_to: '2024-01-07',
      store_address: '123 Test St',
      items: [
        { item: 'Milk', price_display: '$3.99', price_in_cents: 399, quantity: '1L', category_name: 'Dairy', master_item_id: 10 },
        { item: 'Bread', price_display: '$2.49', price_in_cents: 249, quantity: '1 loaf', category_name: 'Bakery', master_item_id: null },
      ],
    };
    const imagePaths = [{ path: '/uploads/flyer-page-1.jpg', mimetype: 'image/jpeg' }];
    const originalFileName = 'my-flyer.pdf';
    const checksum = 'checksum-abc-123';
    const userId = 'user-xyz-456';

    // Act
    const { flyerData, itemsForDb } = await transformer.transform(extractedData, imagePaths, originalFileName, checksum, userId, mockLogger);

    // Assert
    // 0. Check logging
    expect(mockLogger.info).toHaveBeenCalledWith('Starting data transformation from AI output to database format.');
    expect(mockLogger.info).toHaveBeenCalledWith({ itemCount: 2, storeName: 'Test Store' }, 'Data transformation complete.');

    // 1. Check flyer data
    expect(flyerData).toEqual({
      file_name: originalFileName,
      image_url: '/flyer-images/flyer-page-1.jpg',
      icon_url: '/flyer-images/icons/icon-flyer-page-1.webp',
      checksum,
      store_name: 'Test Store',
      valid_from: '2024-01-01',
      valid_to: '2024-01-07',
      store_address: '123 Test St',
      item_count: 2,
      uploaded_by: userId,
    });

    // 2. Check item data
    expect(itemsForDb).toHaveLength(2);
    expect(itemsForDb[0]).toEqual(expect.objectContaining({
      item: 'Milk',
      master_item_id: 10, // Should be passed through
      view_count: 0,
      click_count: 0,
    }));
    expect(itemsForDb[1]).toEqual(expect.objectContaining({
      item: 'Bread',
      master_item_id: undefined, // null should be converted to undefined
      view_count: 0,
      click_count: 0,
    })); // Use a more specific type assertion to check for the added property.
    expect((itemsForDb[0] as FlyerItemInsert & { updated_at: string }).updated_at).toBeTypeOf('string');

    // 3. Check that generateFlyerIcon was called correctly
    expect(generateFlyerIcon).toHaveBeenCalledWith('/uploads/flyer-page-1.jpg', '/uploads/icons', mockLogger);
  });

  it('should handle missing optional data gracefully', async () => {
    // Arrange
    const extractedData: z.infer<typeof AiFlyerDataSchema> = {
      store_name: '', // Empty store name
      valid_from: null,
      valid_to: null,
      store_address: null,
      items: [], // No items
    };
    const imagePaths = [{ path: '/uploads/another.png', mimetype: 'image/png' }];
    const originalFileName = 'another.png';
    const checksum = 'checksum-def-456';
    // No userId provided

    vi.mocked(generateFlyerIcon).mockResolvedValue('icon-another.webp');

    // Act
    const { flyerData, itemsForDb } = await transformer.transform(extractedData, imagePaths, originalFileName, checksum, undefined, mockLogger);

    // Assert
    // 0. Check logging
    expect(mockLogger.info).toHaveBeenCalledWith('Starting data transformation from AI output to database format.');
    expect(mockLogger.info).toHaveBeenCalledWith({ itemCount: 0, storeName: 'Unknown Store (auto)' }, 'Data transformation complete.');

    expect(itemsForDb).toHaveLength(0);
    expect(flyerData).toEqual({
      file_name: originalFileName,
      image_url: '/flyer-images/another.png',
      icon_url: '/flyer-images/icons/icon-another.webp',
      checksum,
      store_name: 'Unknown Store (auto)', // Should use fallback
      valid_from: null,
      valid_to: null,
      store_address: null,
      item_count: 0,
      uploaded_by: undefined, // Should be undefined
    });
  });
});