import { ForbiddenException, NotFoundException } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { ShoppingListService } from '../shopping-list/shopping-list.service';

describe('ShoppingListService', () => {
  const prismaMock = {
    shoppingListItem: {
      findMany: jest.fn(),
      findUnique: jest.fn(),
      update: jest.fn(),
      findFirst: jest.fn(),
      create: jest.fn(),
    },
    flyerSelection: {
      findMany: jest.fn(),
    },
    $transaction: jest.fn(),
  };

  const createService = () => new ShoppingListService(prismaMock as any);

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

  it('throws when updating another users shopping item', async () => {
    prismaMock.shoppingListItem.findUnique.mockResolvedValue({ id: 1, userId: 99 });
    const service = createService();

    await expect(service.updateCheckedStatus(1, 1, true)).rejects.toBeInstanceOf(ForbiddenException);
  });

  it('throws when shopping item is missing', async () => {
    prismaMock.shoppingListItem.findUnique.mockResolvedValue(null);
    const service = createService();

    await expect(service.updateCheckedStatus(1, 1, true)).rejects.toBeInstanceOf(NotFoundException);
  });

  it('deduplicates by productId+unit when planning from flyer selections', async () => {
    prismaMock.flyerSelection.findMany.mockResolvedValue([
      {
        id: 10,
        plannedQuantity: new Prisma.Decimal(1),
        plannedUnit: 'kg',
        item: {
          id: 100,
          rawName: 'Tomat',
          matchedProductId: 7,
          categoryId: 22,
          priceUnit: 'kg',
        },
      },
      {
        id: 11,
        plannedQuantity: new Prisma.Decimal(2),
        plannedUnit: 'kg',
        item: {
          id: 101,
          rawName: 'Tomat',
          matchedProductId: 7,
          categoryId: 22,
          priceUnit: 'kg',
        },
      },
    ]);

    prismaMock.$transaction.mockImplementation(async (cb: any) => cb(prismaMock));
    prismaMock.shoppingListItem.findFirst
      .mockResolvedValueOnce(null)
      .mockResolvedValueOnce({ id: 999 });

    const service = createService();
    const result = await service.upsertFromFlyerSelections(1, 1, [100, 101]);

    expect(result.created).toBe(1);
    expect(result.updated).toBe(1);
    expect(prismaMock.shoppingListItem.create).toHaveBeenCalledTimes(1);
    expect(prismaMock.shoppingListItem.update).toHaveBeenCalledTimes(1);
  });
});
