import { NotFoundException } from '@nestjs/common';
import { ProjectService } from './project.service';

describe('ProjectService domain writes', () => {
  const makeService = () => {
    const prisma = {
      product: {
        findUnique: jest.fn(),
      },
      project: {
        create: jest.fn(),
        delete: jest.fn(),
        findFirst: jest.fn(),
        findMany: jest.fn(),
        update: jest.fn(),
      },
    };

    return {
      prisma,
      service: new ProjectService(prisma as any),
    };
  };

  it('creates projects directly under a product relation row', async () => {
    const { prisma, service } = makeService();
    prisma.product.findUnique.mockResolvedValue({ id: 'product-1' });
    prisma.project.create.mockResolvedValue({ id: 'project-1', productId: 'product-1' });

    await service.create('product-1', { name: 'CRM', description: 'Customer system' });

    expect(prisma.project.create).toHaveBeenCalledWith({
      data: {
        productId: 'product-1',
        name: 'CRM',
        description: 'Customer system',
      },
    });
  });

  it('lists projects by product id', async () => {
    const { prisma, service } = makeService();
    prisma.project.findMany.mockResolvedValue([]);

    await service.findAll('product-1');

    expect(prisma.project.findMany).toHaveBeenCalledWith({
      where: { productId: 'product-1' },
      orderBy: { createdAt: 'desc' },
    });
  });

  it('updates projects only inside their product scope', async () => {
    const { prisma, service } = makeService();
    prisma.project.findFirst.mockResolvedValue({ id: 'project-1', productId: 'product-1' });
    prisma.project.update.mockResolvedValue({ id: 'project-1', name: 'CRM v2' });

    await service.update('product-1', 'project-1', { name: 'CRM v2' });

    expect(prisma.project.update).toHaveBeenCalledWith({
      where: { id: 'project-1' },
      data: { name: 'CRM v2' },
    });
  });

  it('throws when updating a project outside the product scope', async () => {
    const { prisma, service } = makeService();
    prisma.project.findFirst.mockResolvedValue(null);

    await expect(service.update('product-1', 'project-404', { name: 'Ghost' })).rejects.toBeInstanceOf(NotFoundException);
    expect(prisma.project.update).not.toHaveBeenCalled();
  });

  it('deletes projects only inside their product scope', async () => {
    const { prisma, service } = makeService();
    prisma.project.findFirst.mockResolvedValue({ id: 'project-1', productId: 'product-1' });
    prisma.project.delete.mockResolvedValue({ id: 'project-1' });

    await service.remove('product-1', 'project-1');

    expect(prisma.project.delete).toHaveBeenCalledWith({ where: { id: 'project-1' } });
  });
});
