import { ReceiptImportService } from './receipt-import.service';
import { FlatCategory } from '../categories/categories.service';

function cat(id: number, name: string, path: string): FlatCategory {
  return { id, name, path };
}

describe('ReceiptImportService parseReceipt flow', () => {
  const categories: FlatCategory[] = [
    cat(30, 'Mejeri, ost & ägg', 'Mejeri, ost & ägg'),
    cat(53, 'Choklad', 'Glass, godis & snacks > Choklad'),
    cat(51, 'Godis', 'Glass, godis & snacks > Godis'),
  ];

  const prismaMock = {
    aiTrace: { create: jest.fn() },
    receiptAlias: { findMany: jest.fn() },
    product: { findMany: jest.fn() },
    unitMapping: { findMany: jest.fn() },
    user: { findUnique: jest.fn() },
  };

  const aiServiceMock = {
    suggestCategory: jest.fn(),
  };

  const categoriesServiceMock = {
    findFlattened: jest.fn(),
  };

  const service = new ReceiptImportService(
    prismaMock as any,
    aiServiceMock as any,
    categoriesServiceMock as any,
    { commitReceiptMatches: jest.fn() } as any,
  );

  beforeEach(() => {
    jest.clearAllMocks();

    categoriesServiceMock.findFlattened.mockResolvedValue(categories);
    prismaMock.unitMapping.findMany.mockResolvedValue([]);
    prismaMock.user.findUnique.mockResolvedValue({ aiEngineEnabled: true });
  });

  it('kör prioriteringskedjan i parseReceipt: user alias -> global alias -> wordmatch -> AI', async () => {
    prismaMock.receiptAlias.findMany.mockResolvedValue([
      {
        receiptName: 'mixad vara',
        product: {
          id: 901,
          name: 'User Produkt',
          canonicalName: 'User Produkt',
          categoryRef: { id: 30, name: 'Mejeri, ost & ägg' },
        },
      },
      {
        receiptName: 'global choklad',
        product: {
          id: 900,
          name: 'Global Produkt',
          canonicalName: 'Global Produkt',
          categoryRef: { id: 53, name: 'Choklad' },
        },
      },
    ]);

    prismaMock.product.findMany.mockResolvedValue([
      {
        id: 777,
        name: 'Specialprodukt',
        canonicalName: 'Specialprodukt',
        categoryRef: { id: 30, name: 'Mejeri, ost & ägg' },
      },
    ]);

    aiServiceMock.suggestCategory.mockResolvedValue({
      categoryId: 51,
      categoryName: 'Godis',
      path: 'Glass, godis & snacks > Godis',
      confidence: 'low',
    });

    jest
      .spyOn(service as any, 'parseReceiptViaImporter')
      .mockResolvedValue({
        items: [
          { rawName: 'MIXAD VARA', quantity: 1, unit: 'st' },
          { rawName: 'GLOBAL CHOKLAD', quantity: 1, unit: 'st' },
          { rawName: 'SPECIALPRODUKT 1st', quantity: 1, unit: 'st' },
          { rawName: 'helt okänd vara', quantity: 1, unit: 'st' },
        ],
        trace: {
          prompt: 'test prompt',
          rawOutput: '{"items":[]}',
          normalizedOutput: { items: [] },
        },
      });

    const file = {
      buffer: Buffer.from('dummy'),
      mimetype: 'image/jpeg',
      originalname: 'receipt.jpg',
    } as any;

    const result = await service.parseReceipt(file, false, 10);

    expect(result).toHaveLength(4);

    expect(result[0].matchedVia).toBe('alias');
    expect(result[0].matchedProductId).toBe(901);

    expect(result[1].matchedVia).toBe('alias');
    expect(result[1].matchedProductId).toBe(900);

    expect(result[2].matchedVia).toBe('wordmatch');
    expect(result[2].suggestedProductId).toBe(777);
    expect(result[2].categorySuggestion?.categoryId).toBe(30);

    expect(result[3].matchedVia).toBe('none');
    expect(result[3].categorySuggestion?.categoryId).toBe(51);

    expect(aiServiceMock.suggestCategory).toHaveBeenCalledTimes(1);
    expect(aiServiceMock.suggestCategory).toHaveBeenCalledWith('helt okänd vara', categories);
  });
});
