import { describe, expect, it, vi } from 'vitest'

const prismaMock = vi.hoisted(() => ({
  notification: {
    findMany: vi.fn(),
    count: vi.fn(),
    updateMany: vi.fn(),
  },
  notificationPreference: {
    findMany: vi.fn(),
    upsert: vi.fn(),
  },
}))

vi.mock('../../lib/prisma', () => ({ prisma: prismaMock }))

import * as repo from './notification.repo'

describe('notification.repo query boundaries', () => {
  it('scopes company in-app notification lists and applies unread filtering only when requested', async () => {
    await repo.findCompany('company_1', 'true')

    expect(prismaMock.notification.findMany).toHaveBeenCalledWith({
      where: { companyId: 'company_1', channel: 'IN_APP', readAt: null },
      orderBy: { createdAt: 'desc' },
      take: 50,
    })
  })

  it('marks a single company notification read with tenant scoping', async () => {
    vi.useFakeTimers()
    vi.setSystemTime(new Date('2026-06-09T13:00:00.000Z'))

    await repo.markRead('notification_1', 'company_1')

    expect(prismaMock.notification.updateMany).toHaveBeenCalledWith({
      where: { id: 'notification_1', companyId: 'company_1' },
      data: { readAt: new Date('2026-06-09T13:00:00.000Z'), status: 'READ' },
    })
    vi.useRealTimers()
  })

  it('keeps renter bulk read updates constrained to renter in-app notifications', async () => {
    await repo.markAllRenterRead('renter_1')

    expect(prismaMock.notification.updateMany).toHaveBeenCalledWith({
      where: { renterId: 'renter_1', channel: 'IN_APP', readAt: null },
      data: { readAt: expect.any(Date), status: 'READ' },
    })
  })

  it('defaults company notification history to a capped newest-first query', async () => {
    await repo.findCompanyHistory('company_1')

    expect(prismaMock.notification.findMany).toHaveBeenCalledWith({
      where: { companyId: 'company_1' },
      orderBy: { createdAt: 'desc' },
      take: 200,
    })
  })

  it('upserts employee preferences by composite key without cross-employee mutation', async () => {
    await repo.upsertEmployeePreferences('employee_1', [
      { notificationType: 'RESERVATION_CREATED', channel: 'EMAIL', enabled: false },
      { notificationType: 'PAYMENT_RECEIVED', channel: 'IN_APP', enabled: true },
    ])

    expect(prismaMock.notificationPreference.upsert).toHaveBeenCalledTimes(2)
    expect(prismaMock.notificationPreference.upsert).toHaveBeenNthCalledWith(1, {
      where: {
        employeeId_notificationType_channel: {
          employeeId: 'employee_1',
          notificationType: 'RESERVATION_CREATED',
          channel: 'EMAIL',
        },
      },
      create: {
        employeeId: 'employee_1',
        notificationType: 'RESERVATION_CREATED',
        channel: 'EMAIL',
        enabled: false,
      },
      update: { enabled: false },
    })
  })

  it('upserts renter preferences by renter composite key', async () => {
    await repo.upsertRenterPreferences('renter_1', [
      { notificationType: 'RESERVATION_CONFIRMED', channel: 'PUSH', enabled: true },
    ])

    expect(prismaMock.notificationPreference.upsert).toHaveBeenCalledWith({
      where: {
        renterId_notificationType_channel: {
          renterId: 'renter_1',
          notificationType: 'RESERVATION_CONFIRMED',
          channel: 'PUSH',
        },
      },
      create: {
        renterId: 'renter_1',
        notificationType: 'RESERVATION_CONFIRMED',
        channel: 'PUSH',
        enabled: true,
      },
      update: { enabled: true },
    })
  })
})
