import { NotificationService } from './notification.service';

describe('NotificationService', () => {
  const makeService = () => {
    const prisma = {
      notification: {
        create: jest.fn(),
        createMany: jest.fn(),
        findMany: jest.fn(),
        updateMany: jest.fn(),
      },
    };
    return { prisma, service: new NotificationService(prisma as any) };
  };

  it('lists unread notifications for one recipient in newest-first order', async () => {
    const { prisma, service } = makeService();
    prisma.notification.findMany.mockResolvedValue([{ id: 'n-1' }]);

    await expect(service.list({ recipientId: 'm-1', unreadOnly: true, limit: 20 })).resolves.toEqual([{ id: 'n-1' }]);

    expect(prisma.notification.findMany).toHaveBeenCalledWith({
      where: { recipientId: 'm-1', readAt: null },
      orderBy: { createdAt: 'desc' },
      take: 20,
    });
  });

  it('marks one notification as read only for the requesting recipient', async () => {
    const { prisma, service } = makeService();
    prisma.notification.updateMany.mockResolvedValue({ count: 1 });

    await service.markRead('n-1', 'm-1');

    expect(prisma.notification.updateMany).toHaveBeenCalledWith({
      where: { id: 'n-1', recipientId: 'm-1', readAt: null },
      data: { readAt: expect.any(Date) },
    });
  });

  it('marks all unread notifications for one recipient as read', async () => {
    const { prisma, service } = makeService();
    prisma.notification.updateMany.mockResolvedValue({ count: 2 });

    await service.markAllRead('m-1');

    expect(prisma.notification.updateMany).toHaveBeenCalledWith({
      where: { recipientId: 'm-1', readAt: null },
      data: { readAt: expect.any(Date) },
    });
  });

  it('creates notifications with stable V2.7 event types', async () => {
    const { prisma, service } = makeService();
    prisma.notification.create.mockResolvedValue({ id: 'n-risk' });

    await service.create({
      recipientId: 'm-manager',
      actorId: 'xiaobao',
      type: 'risk_alert',
      title: '版本存在延期风险',
      resourceType: 'version',
      resourceId: 'ver-1',
      projectId: 'project-1',
      versionId: 'ver-1',
      metadata: { riskLevel: 'likely_delayed' },
    });

    expect(prisma.notification.create).toHaveBeenCalledWith({
      data: expect.objectContaining({
        recipientId: 'm-manager',
        type: 'risk_alert',
        resourceType: 'version',
        resourceId: 'ver-1',
        metadata: { riskLevel: 'likely_delayed' },
      }),
    });
  });
});
