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

vi.mock('../../lib/prisma', () => ({
  prisma: {
    rentalPayment: { findMany: vi.fn(), findFirst: vi.fn(), findFirstOrThrow: vi.fn(), update: vi.fn(), updateMany: vi.fn(), create: vi.fn() },
    reservation: { findFirstOrThrow: vi.fn(), update: vi.fn(), findUniqueOrThrow: vi.fn() },
    $transaction: vi.fn(async (callback) => callback({
      reservation: {
        findUniqueOrThrow: vi.fn().mockResolvedValue({
          id: 'reservation_1',
          totalAmount: 5000,
          rentalPayments: [{ amount: 2500 }, { amount: 1500 }],
        }),
        update: vi.fn(),
      },
    })),
  },
}))

import { prisma } from '../../lib/prisma'
import * as repo from './payment.repo'

describe('payment.repo edge queries', () => {
  beforeEach(() => vi.clearAllMocks())

  it('loads recent company payments with reservation, customer and vehicle context', async () => {
    await repo.findByCompany('company_1')

    expect(prisma.rentalPayment.findMany).toHaveBeenCalledWith({
      where: { companyId: 'company_1' },
      include: { reservation: { include: { customer: true, vehicle: true } } },
      orderBy: { createdAt: 'desc' },
      take: 100,
    })
  })

  it('finds payment by id only within company and reservation scope', async () => {
    await repo.findPaymentOrThrow('payment_1', 'company_1', 'reservation_1')

    expect(prisma.rentalPayment.findFirstOrThrow).toHaveBeenCalledWith({
      where: { id: 'payment_1', companyId: 'company_1', reservationId: 'reservation_1' },
    })
  })

  it('marks a payment as succeeded with a fresh paidAt timestamp', async () => {
    vi.useFakeTimers()
    vi.setSystemTime(new Date('2026-08-01T12:00:00.000Z'))

    await repo.markPaymentSucceeded('payment_1')

    expect(prisma.rentalPayment.update).toHaveBeenCalledWith({
      where: { id: 'payment_1' },
      data: { status: 'SUCCEEDED', paidAt: new Date('2026-08-01T12:00:00.000Z') },
    })

    vi.useRealTimers()
  })

  it('recomputes paid amount from successful charge payments', async () => {
    await repo.incrementReservationPaid('reservation_1', 2500)

    expect(prisma.$transaction).toHaveBeenCalled()
  })

  it('maps partial refunds to the correct payment status', async () => {
    await repo.setPaymentRefunded('payment_1', true)
    await repo.setPaymentRefunded('payment_2', false)

    expect(prisma.rentalPayment.update).toHaveBeenNthCalledWith(1, {
      where: { id: 'payment_1' },
      data: { status: 'PARTIALLY_REFUNDED' },
    })
    expect(prisma.rentalPayment.update).toHaveBeenNthCalledWith(2, {
      where: { id: 'payment_2' },
      data: { status: 'REFUNDED' },
    })
  })
})
