import { apiFetch } from '@/lib/api'
import { bilingualPrimary } from '@/components/ui/BilingualInput'
import type { CreatedReservation, Customer, ReservationDraft } from './reservationWizard.types'

type AvailabilityResult = { available: boolean }

function isoFromLocal(value: string) {
  return new Date(value).toISOString()
}

export async function checkVehicleAvailability(draft: ReservationDraft) {
  const { vehicleId, startDate, endDate } = draft.rental
  const params = new URLSearchParams({
    startDate: isoFromLocal(startDate),
    endDate: isoFromLocal(endDate),
  })
  return apiFetch<AvailabilityResult>(`/vehicles/${vehicleId}/availability?${params.toString()}`)
}

export async function uploadLicenseImage(customerId: string, file: File) {
  const formData = new FormData()
  formData.append('file', file)
  return apiFetch<Customer>(`/customers/${customerId}/license-image`, {
    method: 'POST',
    body: formData,
  })
}

function customerPayload(draft: ReservationDraft) {
  return {
    firstName: bilingualPrimary(draft.customer.firstName).trim(),
    firstNameAr: draft.customer.firstName.ar.trim() || undefined,
    lastName: bilingualPrimary(draft.customer.lastName).trim(),
    lastNameAr: draft.customer.lastName.ar.trim() || undefined,
    email: draft.customer.email.trim(),
    phone: draft.customer.phone.trim(),
    driverLicense: draft.license.number.trim(),
    dateOfBirth: isoFromLocal(draft.identity.dateOfBirth),
    nationality: draft.identity.nationality.trim(),
    address: {
      fullAddress: draft.identity.fullAddress.trim(),
      identityDocumentNumber: draft.identity.identityDocumentNumber.trim(),
      internationalLicenseNumber: draft.identity.internationalLicenseNumber.trim() || undefined,
    },
    licenseExpiry: isoFromLocal(draft.license.expiry),
    licenseIssuedAt: isoFromLocal(draft.license.issuedAt),
    licenseCountry: draft.license.country.trim(),
    licenseNumber: draft.license.number.trim(),
    licenseCategory: draft.license.category.trim(),
  }
}

function customerPatchPayload(draft: ReservationDraft) {
  return {
    driverLicense: draft.license.number.trim(),
    dateOfBirth: isoFromLocal(draft.identity.dateOfBirth),
    nationality: draft.identity.nationality.trim(),
    address: {
      fullAddress: draft.identity.fullAddress.trim(),
      identityDocumentNumber: draft.identity.identityDocumentNumber.trim(),
      internationalLicenseNumber: draft.identity.internationalLicenseNumber.trim() || undefined,
    },
    licenseExpiry: isoFromLocal(draft.license.expiry),
    licenseIssuedAt: isoFromLocal(draft.license.issuedAt),
    licenseCountry: draft.license.country.trim(),
    licenseNumber: draft.license.number.trim(),
    licenseCategory: draft.license.category.trim(),
  }
}

function reservationPayload(draft: ReservationDraft, customerId: string) {
  return {
    customerId,
    vehicleId: draft.rental.vehicleId,
    startDate: isoFromLocal(draft.rental.startDate),
    endDate: isoFromLocal(draft.rental.endDate),
    pickupLocation: draft.rental.pickupLocation.trim() || undefined,
    returnLocation: draft.rental.returnLocation.trim() || undefined,
    depositAmount: Number.isFinite(Number(draft.payment.depositAmount)) ? Math.max(0, Math.round(Number(draft.payment.depositAmount))) : 0,
    paymentMode: draft.payment.paymentMode,
    additionalDrivers: draft.additionalDrivers.map((driver) => ({
      firstName: bilingualPrimary(driver.firstName).trim(),
      firstNameAr: driver.firstName.ar.trim() || undefined,
      lastName: bilingualPrimary(driver.lastName).trim(),
      lastNameAr: driver.lastName.ar.trim() || undefined,
      email: driver.email.trim() || undefined,
      phone: driver.phone.trim() || undefined,
      driverLicense: driver.driverLicense.trim(),
      licenseExpiry: driver.licenseExpiry ? isoFromLocal(driver.licenseExpiry) : undefined,
      licenseIssuedAt: driver.licenseIssuedAt ? isoFromLocal(driver.licenseIssuedAt) : undefined,
      dateOfBirth: driver.dateOfBirth ? isoFromLocal(driver.dateOfBirth) : undefined,
      nationality: bilingualPrimary(driver.nationality).trim() || undefined,
      nationalityAr: driver.nationality.ar.trim() || undefined,
    })),
    notes: draft.payment.notes.trim() || undefined,
  }
}

export async function submitReservationDraft(
  draft: ReservationDraft,
  options: { onCustomerIdResolved?: (customerId: string) => void } = {},
) {
  const availability = await checkVehicleAvailability(draft)
  if (!availability.available) {
    const error = new Error('vehicle_unavailable') as Error & { code?: string }
    error.code = 'vehicle_unavailable'
    throw error
  }

  let customerId = draft.customer.mode === 'new'
    ? draft.customer.createdCustomerId
    : draft.customer.selectedCustomerId

  if (!customerId) {
    const createdCustomer = await apiFetch<Customer>('/customers', {
      method: 'POST',
      body: JSON.stringify(customerPayload(draft)),
    })
    customerId = createdCustomer.id
    options.onCustomerIdResolved?.(customerId)
  } else {
    await apiFetch<Customer>(`/customers/${customerId}`, {
      method: 'PATCH',
      body: JSON.stringify(customerPatchPayload(draft)),
    })
    options.onCustomerIdResolved?.(customerId)
  }

  if (draft.license.newImageFile) {
    await uploadLicenseImage(customerId, draft.license.newImageFile)
  }

  const reservation = await apiFetch<CreatedReservation>('/reservations', {
    method: 'POST',
    body: JSON.stringify(reservationPayload(draft, customerId)),
  })

  return { reservation, customerId }
}
