'use client'

import { AlertCircle, CalendarDays, Check, ChevronLeft, ChevronRight, Loader2, Mail, MapPin, Phone, UserRound } from 'lucide-react'
import { useMemo, useRef, useState, type ReactNode } from 'react'
import { useRouter } from 'next/navigation'
import { formatCurrency } from '@rentaldrivego/types'
import type { CarplaceMessages } from '@/lib/carplace/messages'
import { carplaceHref } from '@/lib/carplace/routes'
import type { CarplaceLanguage, QuoteResponse, ReservationResult } from '@/lib/carplace/types'
import { CarplaceApiError, carplacePost } from '@/lib/api'

export type BookingInitialValues = {
  pickupLocation?: string
  dropoffLocation?: string
  pickupDate?: string
  pickupTime?: string
  returnDate?: string
  returnTime?: string
  promoCode?: string
  driverAge?: string
}

type FormState = Required<Omit<BookingInitialValues, 'promoCode'>> & {
  promoCode: string
  firstName: string
  lastName: string
  email: string
  phone: string
  notes: string
  consent: boolean
}

export default function ProgressiveBookingFlow({
  vehicleId,
  companySlug,
  vehicleName,
  companyName,
  dailyRate,
  pickupLocations,
  allowDifferentDropoff,
  dropoffLocations,
  language,
  copy,
  initial,
}: {
  vehicleId: string
  companySlug: string
  vehicleName: string
  companyName: string
  dailyRate: number
  pickupLocations: string[]
  allowDifferentDropoff: boolean
  dropoffLocations: string[]
  language: CarplaceLanguage
  copy: CarplaceMessages
  initial?: BookingInitialValues
}) {
  const router = useRouter()
  const idempotencyKey = useRef<string>(createIdempotencyKey())
  const [step, setStep] = useState(1)
  const [quote, setQuote] = useState<QuoteResponse | null>(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [form, setForm] = useState<FormState>({
    pickupLocation: initial?.pickupLocation || pickupLocations[0] || '',
    dropoffLocation: initial?.dropoffLocation || initial?.pickupLocation || pickupLocations[0] || '',
    pickupDate: initial?.pickupDate || '',
    pickupTime: initial?.pickupTime || '10:00',
    returnDate: initial?.returnDate || '',
    returnTime: initial?.returnTime || '10:00',
    promoCode: initial?.promoCode || '',
    driverAge: initial?.driverAge || '25',
    firstName: '',
    lastName: '',
    email: '',
    phone: '',
    notes: '',
    consent: false,
  })

  const today = new Date().toISOString().slice(0, 10)
  const startIso = useMemo(() => toIso(form.pickupDate, form.pickupTime), [form.pickupDate, form.pickupTime])
  const endIso = useMemo(() => toIso(form.returnDate, form.returnTime), [form.returnDate, form.returnTime])

  function update<K extends keyof FormState>(key: K, value: FormState[K]) {
    setForm((current) => ({ ...current, [key]: value }))
    setError(null)
  }

  async function track(eventName: string, metadata?: Record<string, string | number | boolean | null>) {
    try {
      await carplacePost('/carplace/events', {
        eventName,
        companySlug,
        vehicleId,
        path: window.location.pathname,
        metadata,
      })
    } catch {}
  }

  async function validateTrip() {
    if (!form.pickupLocation || !form.pickupDate || !form.returnDate || !startIso || !endIso || new Date(endIso) <= new Date(startIso)) {
      setError(copy.search.invalidDates)
      return
    }

    setLoading(true)
    setError(null)
    try {
      const nextQuote = await carplacePost<QuoteResponse>('/carplace/quotes', {
        vehicleId,
        startDate: startIso,
        endDate: endIso,
        pickupLocation: form.pickupLocation,
        returnLocation: form.dropoffLocation || form.pickupLocation,
        promoCode: form.promoCode || undefined,
      })
      setQuote(nextQuote)
      if (!nextQuote.available) {
        setError(copy.booking.unavailable)
        return
      }
      setStep(2)
      void track('trip_dates_selected', { rentalDays: nextQuote.rentalDays })
    } catch (caught) {
      const apiError = caught as CarplaceApiError
      if (apiError.code === 'unavailable') setError(copy.booking.unavailable)
      else if (apiError.code === 'invalid_dates') setError(copy.search.invalidDates)
      else setError(copy.booking.error)
    } finally {
      setLoading(false)
    }
  }

  function validateContact() {
    if (!form.firstName.trim() || !form.lastName.trim() || !form.email.trim() || !form.phone.trim()) {
      setError(copy.booking.error)
      return
    }
    setStep(3)
    void track('contact_details_started')
  }

  async function submit() {
    if (!form.consent || !startIso || !endIso) {
      setError(copy.booking.error)
      return
    }

    setLoading(true)
    setError(null)
    try {
      // Recheck price and availability immediately before creating the request.
      const refreshedQuote = await carplacePost<QuoteResponse>('/carplace/quotes', {
        vehicleId,
        startDate: startIso,
        endDate: endIso,
        pickupLocation: form.pickupLocation,
        returnLocation: form.dropoffLocation || form.pickupLocation,
        promoCode: form.promoCode || undefined,
      })
      if (!refreshedQuote.available) {
        setStep(1)
        setQuote(refreshedQuote)
        setError(copy.booking.unavailable)
        return
      }
      setQuote(refreshedQuote)

      const result = await carplacePost<ReservationResult>('/carplace/reservations', {
        vehicleId,
        companySlug,
        firstName: form.firstName.trim(),
        lastName: form.lastName.trim(),
        email: form.email.trim(),
        phone: form.phone.trim(),
        driverAge: Number(form.driverAge),
        startDate: startIso,
        endDate: endIso,
        pickupLocation: form.pickupLocation,
        returnLocation: form.dropoffLocation || form.pickupLocation,
        promoCode: form.promoCode || undefined,
        notes: form.notes.trim() || undefined,
        language,
        idempotencyKey: idempotencyKey.current,
      }, {
        headers: { 'Idempotency-Key': idempotencyKey.current },
      })

      const reference = result.bookingReference || result.reservationId
      try {
        sessionStorage.setItem(`carplace-request:${reference}`, JSON.stringify({ ...result, quote: refreshedQuote, vehicleName, companyName }))
      } catch {}
      void track('booking_request_success', { reference })
      router.push(carplaceHref(`/request/${encodeURIComponent(reference)}`))
    } catch (caught) {
      const apiError = caught as CarplaceApiError
      void track('booking_request_failed', { code: apiError.code ?? 'unknown' })
      if (apiError.code === 'unavailable') {
        setStep(1)
        setError(copy.booking.unavailable)
      } else if (apiError.code === 'invalid_dates') {
        setStep(1)
        setError(copy.search.invalidDates)
      } else {
        setError(copy.booking.error)
      }
    } finally {
      setLoading(false)
    }
  }

  return (
    <section className="carplace-booking" aria-labelledby="booking-title">
      <div className="flex items-center justify-between gap-3">
        <div>
          <p className="text-xs font-bold uppercase tracking-[0.18em] text-orange-600 dark:text-orange-400">{copy.vehicle.estimated}</p>
          <h2 id="booking-title" className="mt-1 text-xl font-black text-blue-950 dark:text-white">{copy.booking.title}</h2>
        </div>
        <p className="text-sm font-black text-blue-950 dark:text-white">{formatCurrency(dailyRate, 'MAD', language)} <span className="text-xs font-semibold text-stone-500 dark:text-slate-400">{copy.vehicle.perDay}</span></p>
      </div>

      <ol className="mt-5 grid grid-cols-3 gap-2" aria-label={copy.booking.title}>
        {[copy.booking.stepTrip, copy.booking.stepContact, copy.booking.stepReview].map((label, index) => {
          const number = index + 1
          const active = number === step
          const done = number < step
          return <li key={label} className={`carplace-step ${active ? 'carplace-step-active' : ''} ${done ? 'carplace-step-done' : ''}`}><span>{done ? <Check className="h-3.5 w-3.5" /> : number}</span>{label}</li>
        })}
      </ol>

      {error ? <div className="mt-4 flex gap-2 rounded-xl border border-red-200 bg-red-50 p-3 text-sm text-red-700 dark:border-red-900 dark:bg-red-950/40 dark:text-red-200"><AlertCircle className="mt-0.5 h-4 w-4 shrink-0" />{error}</div> : null}

      {step === 1 ? (
        <div className="mt-5 grid gap-4">
          <BookingField label={copy.search.pickup} icon={MapPin}>
            <select className="carplace-input" value={form.pickupLocation} onChange={(event) => { update('pickupLocation', event.target.value); if (!allowDifferentDropoff) update('dropoffLocation', event.target.value) }} required>
              {pickupLocations.length === 0 ? <option value="">{copy.search.locationPlaceholder}</option> : null}
              {pickupLocations.map((location) => <option key={location}>{location}</option>)}
            </select>
          </BookingField>
          <BookingField label={copy.search.returnLocation} icon={MapPin}>
            {allowDifferentDropoff ? (
              <select className="carplace-input" value={form.dropoffLocation} onChange={(event) => update('dropoffLocation', event.target.value)}>
                {[...new Set([form.pickupLocation, ...dropoffLocations])].filter(Boolean).map((location) => <option key={location}>{location}</option>)}
              </select>
            ) : <div className="carplace-input flex items-center text-stone-600 dark:text-slate-300">{form.pickupLocation || copy.search.sameReturn}</div>}
          </BookingField>
          <div className="grid gap-3 sm:grid-cols-2">
            <BookingField label={copy.search.pickupDate} icon={CalendarDays}>
              <div className="grid grid-cols-[1fr_6.5rem] gap-2"><input type="date" min={today} className="carplace-input min-w-0" value={form.pickupDate} onChange={(event) => update('pickupDate', event.target.value)} /><input type="time" className="carplace-input min-w-0" value={form.pickupTime} onChange={(event) => update('pickupTime', event.target.value)} /></div>
            </BookingField>
            <BookingField label={copy.search.returnDate} icon={CalendarDays}>
              <div className="grid grid-cols-[1fr_6.5rem] gap-2"><input type="date" min={form.pickupDate || today} className="carplace-input min-w-0" value={form.returnDate} onChange={(event) => update('returnDate', event.target.value)} /><input type="time" className="carplace-input min-w-0" value={form.returnTime} onChange={(event) => update('returnTime', event.target.value)} /></div>
            </BookingField>
          </div>
          <label className="grid gap-1 text-xs font-bold text-stone-600 dark:text-slate-300">{copy.search.age}<select className="carplace-input" value={form.driverAge} onChange={(event) => update('driverAge', event.target.value)}><option value="18">18+</option><option value="21">21+</option><option value="23">23+</option><option value="25">25+</option><option value="30">30+</option></select></label>
          <label className="grid gap-1 text-xs font-bold text-stone-600 dark:text-slate-300">{copy.search.promo} <span className="font-normal text-stone-400">({copy.search.optional})</span><input className="carplace-input" value={form.promoCode} onChange={(event) => update('promoCode', event.target.value)} /></label>
          {quote ? <QuoteBox quote={quote} language={language} copy={copy} /> : null}
          <button type="button" className="carplace-primary-button justify-center" onClick={validateTrip} disabled={loading}>{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <ChevronRight className="h-4 w-4 rtl:rotate-180" />}{copy.actions.continue}</button>
        </div>
      ) : null}

      {step === 2 ? (
        <div className="mt-5 grid gap-4">
          <p className="text-sm leading-6 text-stone-600 dark:text-slate-300">{copy.booking.contactIntro}</p>
          <div className="grid gap-3 sm:grid-cols-2">
            <BookingField label={copy.booking.firstName} icon={UserRound}><input className="carplace-input" value={form.firstName} onChange={(event) => update('firstName', event.target.value)} autoComplete="given-name" /></BookingField>
            <BookingField label={copy.booking.lastName} icon={UserRound}><input className="carplace-input" value={form.lastName} onChange={(event) => update('lastName', event.target.value)} autoComplete="family-name" /></BookingField>
          </div>
          <BookingField label={copy.booking.email} icon={Mail}><input type="email" className="carplace-input" value={form.email} onChange={(event) => update('email', event.target.value)} autoComplete="email" /></BookingField>
          <BookingField label={copy.booking.phone} icon={Phone}><input type="tel" className="carplace-input" value={form.phone} onChange={(event) => update('phone', event.target.value)} autoComplete="tel" /></BookingField>
          <label className="grid gap-1 text-xs font-bold text-stone-600 dark:text-slate-300">{copy.booking.notes} <span className="font-normal text-stone-400">({copy.search.optional})</span><textarea className="carplace-input min-h-24 resize-y" value={form.notes} onChange={(event) => update('notes', event.target.value)} placeholder={copy.booking.notesPlaceholder} maxLength={500} /></label>
          <div className="grid grid-cols-2 gap-2"><button type="button" className="carplace-secondary-button justify-center" onClick={() => setStep(1)}><ChevronLeft className="h-4 w-4 rtl:rotate-180" />{copy.actions.back}</button><button type="button" className="carplace-primary-button justify-center" onClick={validateContact}><ChevronRight className="h-4 w-4 rtl:rotate-180" />{copy.actions.continue}</button></div>
        </div>
      ) : null}

      {step === 3 ? (
        <div className="mt-5 grid gap-4">
          <h3 className="text-base font-black text-blue-950 dark:text-white">{copy.booking.reviewTitle}</h3>
          <dl className="grid gap-3 rounded-2xl bg-stone-50 p-4 text-sm dark:bg-blue-950/60">
            <ReviewRow label={copy.vehicle.company} value={companyName} />
            <ReviewRow label={copy.actions.viewVehicle} value={vehicleName} />
            <ReviewRow label={copy.search.pickup} value={`${form.pickupLocation} · ${formatLocalDate(startIso, language)}`} />
            <ReviewRow label={copy.search.returnLocation} value={`${form.dropoffLocation || form.pickupLocation} · ${formatLocalDate(endIso, language)}`} />
            <ReviewRow label={copy.booking.email} value={form.email} />
            <ReviewRow label={copy.booking.phone} value={form.phone} />
            <ReviewRow label={copy.search.age} value={`${form.driverAge}+`} />
          </dl>
          {quote ? <QuoteBox quote={quote} language={language} copy={copy} /> : null}
          <p className="rounded-xl border border-amber-200 bg-amber-50 p-3 text-sm leading-6 text-amber-900 dark:border-amber-900 dark:bg-amber-950/40 dark:text-amber-100">{copy.booking.pendingNotice}</p>
          <label className="flex items-start gap-3 text-sm leading-6 text-stone-700 dark:text-slate-200"><input type="checkbox" className="mt-1 h-4 w-4 accent-orange-600" checked={form.consent} onChange={(event) => update('consent', event.target.checked)} /><span>{copy.booking.consent}</span></label>
          <div className="grid grid-cols-2 gap-2"><button type="button" className="carplace-secondary-button justify-center" onClick={() => setStep(2)} disabled={loading}><ChevronLeft className="h-4 w-4 rtl:rotate-180" />{copy.actions.back}</button><button type="button" className="carplace-primary-button justify-center" onClick={submit} disabled={loading || !form.consent}>{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Check className="h-4 w-4" />}{copy.actions.submit}</button></div>
        </div>
      ) : null}
    </section>
  )
}

function BookingField({ label, icon: Icon, children }: { label: string; icon: typeof MapPin; children: ReactNode }) {
  return <label className="grid gap-1 text-xs font-bold text-stone-600 dark:text-slate-300"><span className="flex items-center gap-2"><Icon className="h-4 w-4 text-orange-600 dark:text-orange-400" />{label}</span>{children}</label>
}

function ReviewRow({ label, value }: { label: string; value: string }) {
  return <div className="grid gap-1 sm:grid-cols-[8rem_1fr]"><dt className="font-semibold text-stone-500 dark:text-slate-400">{label}</dt><dd className="font-semibold text-blue-950 dark:text-white">{value}</dd></div>
}

function QuoteBox({ quote, language, copy }: { quote: QuoteResponse; language: CarplaceLanguage; copy: CarplaceMessages }) {
  return <div className="rounded-2xl border border-blue-100 bg-blue-50 p-4 dark:border-blue-900 dark:bg-blue-950/60"><div className="flex items-center justify-between gap-3"><div><p className="text-xs font-bold uppercase tracking-[0.14em] text-blue-700 dark:text-blue-300">{copy.vehicle.estimated}</p><p className="mt-1 text-xs text-stone-500 dark:text-slate-400">{quote.rentalDays} × {formatCurrency(quote.dailyRate, 'MAD', language)}</p></div><p className="text-xl font-black text-blue-950 dark:text-white">{formatCurrency(quote.estimatedTotal, 'MAD', language)}</p></div><p className="mt-3 text-xs leading-5 text-stone-600 dark:text-slate-300">{copy.vehicle.estimateDisclaimer}</p></div>
}

function toIso(date: string, time: string): string | null {
  if (!date || !time) return null
  const value = new Date(`${date}T${time}:00`)
  return Number.isNaN(value.getTime()) ? null : value.toISOString()
}

function formatLocalDate(value: string | null, language: CarplaceLanguage): string {
  if (!value) return ''
  return new Intl.DateTimeFormat(language === 'ar' ? 'ar-MA' : language === 'fr' ? 'fr-MA' : 'en-MA', { dateStyle: 'medium', timeStyle: 'short' }).format(new Date(value))
}

function createIdempotencyKey(): string {
  if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID()
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (character) => {
    const random = Math.floor(Math.random() * 16)
    const value = character === 'x' ? random : (random & 0x3) | 0x8
    return value.toString(16)
  })
}
