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

vi.mock('./notification.repo', () => ({
  findCompany: vi.fn(),
  findCompanyHistory: vi.fn(),
  countUnread: vi.fn(),
  markRead: vi.fn(),
  markAllRead: vi.fn(),
  findEmployeePreferences: vi.fn(),
  upsertEmployeePreferences: vi.fn(),
  findRenter: vi.fn(),
  markRenterRead: vi.fn(),
  markAllRenterRead: vi.fn(),
  findRenterPreferences: vi.fn(),
  upsertRenterPreferences: vi.fn(),
}))

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

describe('notification.service', () => {
  beforeEach(() => vi.clearAllMocks())

  it('delegates company notification reads and history filters without rewriting query semantics', async () => {
    vi.mocked(repo.findCompany).mockResolvedValue([{ id: 'n1' }] as never)
    vi.mocked(repo.findCompanyHistory).mockResolvedValue([{ id: 'h1' }] as never)
    vi.mocked(repo.countUnread).mockResolvedValue(4 as never)

    await expect(service.listCompany('company_1', 'true')).resolves.toEqual([{ id: 'n1' }])
    await expect(service.listCompanyHistory('company_1', { channel: 'EMAIL', status: 'FAILED', limit: 25 })).resolves.toEqual([{ id: 'h1' }])
    await expect(service.countUnread('company_1')).resolves.toBe(4)

    expect(repo.findCompany).toHaveBeenCalledWith('company_1', 'true')
    expect(repo.findCompanyHistory).toHaveBeenCalledWith('company_1', { channel: 'EMAIL', status: 'FAILED', limit: 25 })
    expect(repo.countUnread).toHaveBeenCalledWith('company_1')
  })

  it('marks company notifications read only within the company tenant', async () => {
    await service.markRead('notification_1', 'company_1')
    await service.markAllRead('company_1')

    expect(repo.markRead).toHaveBeenCalledWith('notification_1', 'company_1')
    expect(repo.markAllRead).toHaveBeenCalledWith('company_1')
  })

  it('reads and writes employee preferences through the employee identity, not the company id', async () => {
    const prefs = [{ notificationType: 'BOOKING_CONFIRMED', channel: 'EMAIL', enabled: true }]
    vi.mocked(repo.findEmployeePreferences).mockResolvedValue(prefs as never)

    await expect(service.getPreferences('employee_1')).resolves.toEqual(prefs)
    await service.setPreferences('employee_1', prefs)

    expect(repo.findEmployeePreferences).toHaveBeenCalledWith('employee_1')
    expect(repo.upsertEmployeePreferences).toHaveBeenCalledWith('employee_1', prefs)
  })

  it('keeps renter notification operations scoped to the renter identity', async () => {
    const prefs = [{ notificationType: 'REVIEW_REQUEST', channel: 'IN_APP', enabled: false }]
    vi.mocked(repo.findRenter).mockResolvedValue([{ id: 'rn1' }] as never)
    vi.mocked(repo.findRenterPreferences).mockResolvedValue(prefs as never)

    await service.listRenter('renter_1')
    await service.markRenterRead('notification_1', 'renter_1')
    await service.markAllRenterRead('renter_1')
    await service.getRenterPreferences('renter_1')
    await service.setRenterPreferences('renter_1', prefs)

    expect(repo.findRenter).toHaveBeenCalledWith('renter_1')
    expect(repo.markRenterRead).toHaveBeenCalledWith('notification_1', 'renter_1')
    expect(repo.markAllRenterRead).toHaveBeenCalledWith('renter_1')
    expect(repo.findRenterPreferences).toHaveBeenCalledWith('renter_1')
    expect(repo.upsertRenterPreferences).toHaveBeenCalledWith('renter_1', prefs)
  })
})
