import { describe, expect, it } from 'vitest'
import { buildBillingInvoice } from './billing.service'

const baseReservation = {
  id: 'reservation_1',
  invoiceNumber: 'INV-001',
  contractNumber: 'CON-001',
  status: 'CONFIRMED',
  paymentStatus: 'UNPAID',
  startDate: new Date('2026-06-01T10:00:00.000Z'),
  endDate: new Date('2026-06-05T10:00:00.000Z'),
  totalAmount: 100000,
  depositAmount: 20000,
  customer: { firstName: 'Nora', lastName: 'Driver', email: 'nora@example.com' },
  vehicle: { make: 'Dacia', model: 'Duster', licensePlate: '123-A-6' },
}

function payment(overrides: Partial<any>) {
  return {
    id: `payment_${Math.random()}`,
    reservationId: 'reservation_1',
    amount: 10000,
    currency: 'MAD',
    status: 'SUCCEEDED',
    type: 'CHARGE',
    paymentProvider: 'MANUAL',
    paymentMethod: 'CASH',
    paidAt: new Date('2026-06-01T12:00:00.000Z'),
    createdAt: new Date('2026-06-01T12:00:00.000Z'),
    ...overrides,
  }
}

describe('billing.service buildBillingInvoice', () => {
  it('keeps invoice charges and security deposits in separate balances', () => {
    const invoice = buildBillingInvoice({
      ...baseReservation,
      rentalPayments: [
        payment({ amount: 100000, type: 'CHARGE' }),
        payment({ amount: 5000, type: 'DEPOSIT' }),
      ],
    })

    expect(invoice.invoicePaid).toBe(100000)
    expect(invoice.invoiceBalanceDue).toBe(0)
    expect(invoice.depositCollected).toBe(5000)
    expect(invoice.depositOutstanding).toBe(15000)
    expect(invoice.paymentStatus).toBe('PAID')
    expect(invoice.depositStatus).toBe('PARTIALLY_COLLECTED')
  })

  it('does not count failed or pending payments as collected', () => {
    const invoice = buildBillingInvoice({
      ...baseReservation,
      rentalPayments: [
        payment({ amount: 30000, type: 'CHARGE', status: 'PENDING' }),
        payment({ amount: 20000, type: 'DEPOSIT', status: 'FAILED' }),
      ],
    })

    expect(invoice.invoicePaid).toBe(0)
    expect(invoice.invoiceBalanceDue).toBe(100000)
    expect(invoice.depositCollected).toBe(0)
    expect(invoice.depositOutstanding).toBe(20000)
  })
})
