import { PrismaNotificationPreferenceRepository } from '../repositories/prisma-notification-preference.repository';

describe('PrismaNotificationPreferenceRepository', () => {
  let repository: PrismaNotificationPreferenceRepository;
  let mockPrisma: {
    notificationPreference: {
      findMany: ReturnType<typeof vi.fn>;
      findUnique: ReturnType<typeof vi.fn>;
      upsert: ReturnType<typeof vi.fn>;
    };
  };

  const mockPreference = {
    id: 'pref-1',
    userId: 'user-1',
    channel: 'EMAIL',
    eventType: 'user.registered',
    enabled: true,
    createdAt: new Date(),
    updatedAt: new Date(),
  };

  beforeEach(() => {
    mockPrisma = {
      notificationPreference: {
        findMany: vi.fn(),
        findUnique: vi.fn(),
        upsert: vi.fn(),
      },
    };
    repository = new PrismaNotificationPreferenceRepository(mockPrisma as any);
  });

  it('findByUserId returns preferences for user', async () => {
    const preferences = [mockPreference, { ...mockPreference, id: 'pref-2', channel: 'PUSH' }];
    mockPrisma.notificationPreference.findMany.mockResolvedValue(preferences);

    const result = await repository.findByUserId('user-1');

    expect(mockPrisma.notificationPreference.findMany).toHaveBeenCalledWith(
      expect.objectContaining({ where: { userId: 'user-1' } }),
    );
    expect(result).toHaveLength(2);
    expect(result[0]!.userId).toBe('user-1');
  });

  it('isEnabled returns true when no preference exists (default)', async () => {
    mockPrisma.notificationPreference.findUnique.mockResolvedValue(null);

    const result = await repository.isEnabled('user-1', 'EMAIL', 'user.registered');

    expect(result).toBe(true);
  });

  it('isEnabled returns false when preference is disabled', async () => {
    mockPrisma.notificationPreference.findUnique.mockResolvedValue({
      ...mockPreference,
      enabled: false,
    });

    const result = await repository.isEnabled('user-1', 'EMAIL', 'user.registered');

    expect(result).toBe(false);
  });

  it('isEnabled returns true when preference is enabled', async () => {
    mockPrisma.notificationPreference.findUnique.mockResolvedValue({
      ...mockPreference,
      enabled: true,
    });

    const result = await repository.isEnabled('user-1', 'EMAIL', 'user.registered');

    expect(result).toBe(true);
  });

  it('upsert creates or updates preference', async () => {
    mockPrisma.notificationPreference.upsert.mockResolvedValue(mockPreference);

    const result = await repository.upsert('user-1', 'EMAIL', 'user.registered', true);

    expect(mockPrisma.notificationPreference.upsert).toHaveBeenCalledWith(
      expect.objectContaining({
        where: { userId_channel_eventType: { userId: 'user-1', channel: 'EMAIL', eventType: 'user.registered' } },
        create: { userId: 'user-1', channel: 'EMAIL', eventType: 'user.registered', enabled: true },
        update: { enabled: true },
      }),
    );
    expect(result.userId).toBe('user-1');
    expect(result.enabled).toBe(true);
  });
});
