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

vi.mock('../lib/prisma', () => ({
  prisma: {
    contractSettings: { findUnique: vi.fn() },
    additionalDriver: { createMany: vi.fn() },
    reservation: { update: vi.fn() },
    $transaction: vi.fn(),
  },
}))

import { prisma } from '../lib/prisma'
import { applyAdditionalDriversToReservation, calculateAdditionalDriverCharge } from './additionalDriverService'

describe('additionalDriverService', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    vi.setSystemTime(new Date('2026-06-09T12:00:00.000Z'))
  })

  it('calculates additional driver charges by configured charge mode', () => {
    expect(calculateAdditionalDriverCharge('PER_DAY', 40, 5)).toBe(200)
    expect(calculateAdditionalDriverCharge('FLAT', 150, 5)).toBe(150)
    expect(calculateAdditionalDriverCharge('FREE', 150, 5)).toBe(0)
  })

  it('returns a zero-impact result without touching Prisma when no drivers are supplied', async () => {
    await expect(applyAdditionalDriversToReservation('reservation_1', 'company_1', [], 4)).resolves.toEqual({
      records: [],
      additionalDriverTotal: 0,
      requiresManualApproval: false,
    })
    expect(prisma.contractSettings.findUnique).not.toHaveBeenCalled()
  })

  it('applies charge settings, license risk flags, and reservation totals in one transaction', async () => {
    vi.mocked(prisma.contractSettings.findUnique).mockResolvedValue({
      additionalDriverCharge: 'PER_DAY',
      additionalDriverDailyRate: 75,
      additionalDriverFlatRate: 300,
    } as never)
    vi.mocked(prisma.$transaction).mockResolvedValue([] as never)

    const result = await applyAdditionalDriversToReservation('reservation_1', 'company_1', [
      { firstName: 'Nora', lastName: 'Safe', driverLicense: 'A123', licenseExpiry: '2027-06-09T12:00:00.000Z' },
      { firstName: 'Imad', lastName: 'Risky', driverLicense: 'B456', licenseExpiry: '2026-06-20T12:00:00.000Z' },
    ], 4)

    expect(result.additionalDriverTotal).toBe(600)
    expect(result.requiresManualApproval).toBe(true)
    expect(result.records).toEqual([
      expect.objectContaining({ firstName: 'Nora', totalCharge: 300, requiresApproval: false, approvalNote: null }),
      expect.objectContaining({ firstName: 'Imad', totalCharge: 300, requiresApproval: true, licenseExpiringSoon: true }),
    ])
    expect(prisma.additionalDriver.createMany).toHaveBeenCalledWith({ data: result.records })
    expect(prisma.reservation.update).toHaveBeenCalledWith({
      where: { id: 'reservation_1' },
      data: { additionalDriverTotal: 600, totalAmount: { increment: 600 } },
    })
  })
})
