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

vi.mock('../../lib/storage', () => ({
  getProtectedCustomerLicenseImageUrl: vi.fn((customerId: string) => `/api/v1/customers/${customerId}/license-image`),
}))

import {
  buildReservationWorkflow,
  normalizeOptionalString,
  parseReservationExtras,
  serializeReservationForDashboard,
} from './reservation.presenter'

describe('reservation.presenter boundary behavior', () => {
  it('treats missing, array and primitive extras as empty objects', () => {
    expect(parseReservationExtras(null)).toEqual({})
    expect(parseReservationExtras(['paymentMode'])).toEqual({})
    expect(parseReservationExtras('cash')).toEqual({})
    expect(parseReservationExtras({ paymentMode: 'CASH' })).toEqual({ paymentMode: 'CASH' })
  })

  it('normalizes optional strings without preserving whitespace-only values', () => {
    expect(normalizeOptionalString('  hello  ')).toBe('hello')
    expect(normalizeOptionalString('   ')).toBeNull()
    expect(normalizeOptionalString(null)).toBeNull()
    expect(normalizeOptionalString(undefined)).toBeNull()
  })

  it('locks core edits after contract generation even when reservation is still confirmed', () => {
    expect(buildReservationWorkflow({
      status: 'CONFIRMED',
      contractNumber: 'CTR-1',
      invoiceNumber: null,
      extras: {},
    })).toMatchObject({
      contractGenerated: true,
      closed: false,
      coreEditable: false,
      checkInInspectionEditable: true,
    })
  })

  it('marks closed reservations as immutable and exposes close metadata from extras only when strings', () => {
    expect(buildReservationWorkflow({
      status: 'COMPLETED',
      contractNumber: null,
      invoiceNumber: null,
      extras: { reservationClosedAt: '2026-06-01T12:00:00.000Z', reservationClosedBy: 123 },
    })).toMatchObject({
      closed: true,
      closedAt: '2026-06-01T12:00:00.000Z',
      closedBy: null,
      coreEditable: false,
      returnEditable: false,
      checkOutInspectionEditable: false,
    })
  })

  it('serializes dashboard reservations with protected license URLs and payment mode extraction', () => {
    const result = serializeReservationForDashboard({
      id: 'reservation_1',
      status: 'DRAFT',
      source: 'CARPLACE',
      contractNumber: null,
      invoiceNumber: null,
      paymentStatus: 'UNPAID',
      extras: { paymentMode: 'CARD' },
      customer: {
        id: 'customer_1',
        driverLicense: null,
        dateOfBirth: null,
        address: {},
        licenseImageUrl: '/storage/raw-license.jpg',
        licenseValidationStatus: 'PENDING',
      },
    })

    expect(result.paymentMode).toBe('CARD')
    expect(result.customer?.licenseImageUrl).toBe('/api/v1/customers/customer_1/license-image')
    expect(result.workflow.coreEditable).toBe(true)
  })

  it('does not invent protected license URLs when customer has no stored license image', () => {
    const result = serializeReservationForDashboard({
      id: 'reservation_1',
      status: 'DRAFT',
      source: 'CARPLACE',
      contractNumber: null,
      invoiceNumber: null,
      paymentStatus: 'UNPAID',
      extras: { paymentMode: 42 },
      customer: {
        id: 'customer_1',
        driverLicense: null,
        dateOfBirth: null,
        address: {},
        licenseImageUrl: null,
        licenseValidationStatus: 'PENDING',
      },
    })

    expect(result.paymentMode).toBeNull()
    expect(result.customer?.licenseImageUrl).toBeNull()
  })
})
