import { Test, TestingModule } from '@nestjs/testing';
import { FlyerNormalizerService } from './flyer-normalizer.service';

describe('FlyerNormalizerService', () => {
  let service: FlyerNormalizerService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [FlyerNormalizerService],
    }).compile();

    service = module.get<FlyerNormalizerService>(FlyerNormalizerService);
  });

  it('should be defined', () => {
    expect(service).toBeDefined();
  });

  describe('normalize', () => {
    it('should normalize a valid item', () => {
      const items = [
        {
          rawName: 'KALLRÖKT LAX, GRAVAD LAX',
          normalizedName: 'kallrökt lax gravad lax',
          category: 'Fisk',
          price: 39.9,
          comparisonPrice: 266.0,
          unit: 'kg',
          offer: ['Max 3 köp/hushåll'],
          confidence: 0.85,
          reasonCodes: ['ai_parsed'],
        },
      ];

      const result = service.normalize(items);

      expect(result).toHaveLength(1);
      expect(result[0].rawName).toBe('KALLRÖKT LAX, GRAVAD LAX');
      expect(result[0].price).toBe(39.9);
      expect(result[0].priceUnit).toBe('kg');
      expect(result[0].categoryHint).toBe('Fisk');
    });

    it('should handle missing fields gracefully', () => {
      const items = [
        {
          name: 'PRODUKT',
          // andra fält saknas
        },
      ];

      const result = service.normalize(items);

      expect(result).toHaveLength(1);
      expect(result[0].rawName).toBe('PRODUKT');
      expect(result[0].price).toBeNull();
      expect(result[0].categoryHint).toBeNull();
    });

    it('should skip items without name', () => {
      const items = [
        { price: 100 }, // no name
        { rawName: 'VALID PRODUCT', price: 50 },
      ];

      const result = service.normalize(items);

      expect(result).toHaveLength(1);
      expect(result[0].rawName).toBe('VALID PRODUCT');
    });

    it('should normalize units correctly', () => {
      const items = [
        { rawName: 'Mjölk', unit: 'L' },
        { rawName: 'Smör', unit: 'styck' },
        { rawName: 'Socker', unit: 'KG' },
      ];

      const result = service.normalize(items);

      expect(result).toHaveLength(3);
      expect(result[0].priceUnit).toBe('l');
      expect(result[1].priceUnit).toBe('st');
      expect(result[2].priceUnit).toBe('kg');
    });

    it('should parse Swedish prices correctly', () => {
      const items = [
        { rawName: 'Produkt1', price: '39,90' },
        { rawName: 'Produkt2', price: 39.9 },
        { rawName: 'Produkt3', price: '100' },
      ];

      const result = service.normalize(items);

      expect(result[0].price).toBe(39.9);
      expect(result[1].price).toBe(39.9);
      expect(result[2].price).toBe(100);
    });

    it('should return empty list for non-array input', () => {
      const result = service.normalize(null as any);
      expect(result).toEqual([]);

      const result2 = service.normalize(undefined as any);
      expect(result2).toEqual([]);
    });

    it('splits listed cheese variants into separate products', () => {
      const items = [
        {
          rawName: 'PRÄST®, HERRGÅRD®, GREVÉ®',
          brand: 'ARLA KO',
          unit: 'kg',
          comparisonPrice: '79,90',
          offer: ['Max 3 förp/hushåll'],
        },
      ];

      const result = service.normalize(items);

      expect(result).toHaveLength(3);
      expect(result.map((item) => item.rawName)).toEqual(['Prästost', 'Herrgårdsost', 'Greveost']);
      expect(result.every((item) => item.brand === 'Arla Ko')).toBe(true);
      expect(result.every((item) => item.categoryHint === 'Hårdost')).toBe(true);
      expect(result[0].parseReasons).toContain('split_cheese_variants');
    });

    it('keeps single cheese item unsplit but normalizes brand/category', () => {
      const items = [
        {
          rawName: 'Prästost',
          brand: 'arla ko',
        },
      ];

      const result = service.normalize(items);

      expect(result).toHaveLength(1);
      expect(result[0].rawName).toBe('Prästost');
      expect(result[0].brand).toBe('Arla Ko');
      expect(result[0].categoryHint).toBe('Hårdost');
    });

    it('fixes known OCR typo for spröd', () => {
      const items = [
        {
          rawName: 'Pröd Bakad Firre',
          brand: 'Findus',
        },
      ];

      const result = service.normalize(items);

      expect(result).toHaveLength(1);
      expect(result[0].rawName).toBe('Spröd Bakad Firre');
      expect(result[0].normalizedName).toBe('spröd bakad firre');
    });

    it('does not apply spröd typo fix outside known fish context', () => {
      const items = [
        {
          rawName: 'Pröd tvättmedel',
          brand: 'Test',
        },
      ];

      const result = service.normalize(items);

      expect(result).toHaveLength(1);
      expect(result[0].rawName).toBe('Pröd tvättmedel');
    });

    it('fixes herggårdsost only in cheese context', () => {
      const items = [
        {
          rawName: 'Herggårdsost 31%',
          brand: 'Arla Ko',
        },
      ];

      const result = service.normalize(items);

      expect(result).toHaveLength(1);
      expect(result[0].rawName).toContain('Herrgårdsost');
    });
  });
});
