import { ForbiddenException, NotFoundException } from '@nestjs/common';
import { ProductsService } from './products.service';

describe('ProductsService.updateCategoryMine', () => {
  const prismaMock = {
    product: {
      findUnique: jest.fn(),
      update: jest.fn(),
    },
    category: {
      findUnique: jest.fn(),
    },
  };

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

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

  const service = new ProductsService(
    prismaMock as any,
    aiServiceMock as any,
    categoriesServiceMock as any,
  );

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

  it('kastar NotFound om produkt saknas', async () => {
    prismaMock.product.findUnique.mockResolvedValue(null);

    await expect(service.updateCategoryMine(42, 100, 5)).rejects.toBeInstanceOf(NotFoundException);
  });

  it('kastar Forbidden om produkten inte ägs av användaren', async () => {
    prismaMock.product.findUnique.mockResolvedValue({
      id: 100,
      ownerId: 7,
      isPrivate: true,
    });

    await expect(service.updateCategoryMine(42, 100, 5)).rejects.toBeInstanceOf(ForbiddenException);
  });

  it('kastar Forbidden för globala produkter', async () => {
    prismaMock.product.findUnique.mockResolvedValue({
      id: 100,
      ownerId: 42,
      isPrivate: false,
    });

    await expect(service.updateCategoryMine(42, 100, 5)).rejects.toBeInstanceOf(ForbiddenException);
    expect(prismaMock.product.update).not.toHaveBeenCalled();
  });

  it('kastar NotFound om kategori saknas', async () => {
    prismaMock.product.findUnique.mockResolvedValue({
      id: 100,
      ownerId: 42,
      isPrivate: true,
    });
    prismaMock.category.findUnique.mockResolvedValue(null);

    await expect(service.updateCategoryMine(42, 100, 9999)).rejects.toBeInstanceOf(NotFoundException);
    expect(prismaMock.product.update).not.toHaveBeenCalled();
  });

  it('uppdaterar kategori för ägd icke-global produkt', async () => {
    prismaMock.product.findUnique.mockResolvedValue({
      id: 100,
      ownerId: 42,
      isPrivate: true,
    });
    prismaMock.category.findUnique.mockResolvedValue({ id: 5 });
    prismaMock.product.update.mockResolvedValue({ id: 100, categoryId: 5 });

    await expect(service.updateCategoryMine(42, 100, 5)).resolves.toEqual({
      id: 100,
      categoryId: 5,
    });
    expect(prismaMock.product.update).toHaveBeenCalledWith({
      where: { id: 100 },
      data: { categoryId: 5 },
      select: { id: true, categoryId: true },
    });
  });
});
