import { Head, Link, router } from '@inertiajs/react';
import {
    ArrowLeft,
    ArrowRight,
    BriefcaseBusiness,
    Check,
    Luggage,
    Mail,
    Minus,
    Phone,
    Plane,
    Plus,
    Star,
    UserRound,
    Users,
} from 'lucide-react';
import type { ComponentProps, ReactNode } from 'react';
import { useState } from 'react';
import PageIntro from '@/components/booking/page-intro';
import { cardClass } from '@/components/booking/styles';
import type { Vehicle } from '@/components/booking/vehicles';
import { vehicleIcon } from '@/components/booking/vehicles';
import SiteFooter from '@/components/home/site-footer';
import SiteHeader from '@/components/home/site-header';
import InputError from '@/components/input-error';
import ToggleSwitch from '@/components/onboarding/toggle-switch';
import { cn } from '@/lib/utils';
import { vehicles } from '@/routes/booking';
import type {
    BookingContact,
    TripSummary,
} from '@/types/booking';

type Props = {
    trip: TripSummary;
    vehicle: Vehicle;
    contact: BookingContact;
};

type Errors = Partial<Record<string, string>>;

type ChildSeat = 'child' | 'booster' | 'infant';

const childSeats: { id: ChildSeat; name: string; range: string }[] = [
    {
        id: 'child',
        name: 'Child Safety Seat',
        range: '15–36 kg (approx. 4–11 yrs)',
    },
    {
        id: 'booster',
        name: 'Booster Cushion',
        range: '22–36 kg (approx. 6–12 yrs)',
    },
    {
        id: 'infant',
        name: 'Infant Rear-Facing',
        range: '0–13 kg (approx. 0–15 mos)',
    },
];

const inputClass =
    'w-full rounded-lg border border-navy/15 bg-white px-3.5 py-3 text-sm text-navy outline-none placeholder:text-gray-400 focus:border-gold focus:ring-2 focus:ring-gold/20 dark:border-white/20 dark:bg-ink dark:text-white';

const dividerClass = 'border-navy/10 dark:border-white/10';

function childSeatTotal(seats: Record<ChildSeat, number>): number {
    return seats.child + seats.booster + seats.infant;
}

function parsePickup(value: string): Date {
    const [date, time] = value.split(' ');
    const [year, month, day] = date.split('-').map(Number);
    const [hour, minute] = time.split(':').map(Number);

    return new Date(year, month - 1, day, hour, minute);
}

function formatTime(date: Date): string {
    return date.toLocaleTimeString('en-US', {
        hour: '2-digit',
        minute: '2-digit',
    });
}

function formatDay(date: Date): string {
    return date.toLocaleDateString('en-US', {
        weekday: 'short',
        month: 'short',
        day: 'numeric',
    });
}

function Field({
    id,
    label,
    error,
    icon,
    children,
}: {
    id: string;
    label: string;
    error?: string;
    icon?: ReactNode;
    children: ReactNode;
}) {
    return (
        <div>
            <label htmlFor={id} className="text-xs font-semibold">
                {label}
            </label>
            <div className="relative mt-2">
                {icon && (
                    <span className="pointer-events-none absolute top-1/2 left-3.5 -translate-y-1/2 text-navy/50 dark:text-white/60">
                        {icon}
                    </span>
                )}
                {children}
            </div>
            <InputError message={error} className="mt-1 text-xs" />
        </div>
    );
}

function TextInput({
    withIcon = false,
    ...props
}: ComponentProps<'input'> & { withIcon?: boolean }) {
    return <input className={cn(inputClass, withIcon && 'pl-10')} {...props} />;
}

function Stepper({
    label,
    value,
    min = 0,
    max,
    onChange,
    compact = false,
}: {
    label: string;
    value: number;
    min?: number;
    max: number;
    onChange: (value: number) => void;
    compact?: boolean;
}) {
    const buttonClass = cn(
        'flex items-center justify-center rounded-md transition-colors enabled:hover:bg-gold/15 disabled:opacity-30',
        compact ? 'size-6' : 'size-9',
    );
    const iconClass = compact ? 'size-3' : 'size-4';

    return (
        <div
            className={cn(
                'flex shrink-0 items-center rounded-lg border border-navy/15 dark:border-white/20',
                compact ? 'gap-1 p-0.5' : 'gap-3 p-1.5',
            )}
        >
            <button
                type="button"
                onClick={() => onChange(value - 1)}
                disabled={value <= min}
                aria-label={`Fewer ${label}`}
                className={buttonClass}
            >
                <Minus className={iconClass} />
            </button>
            <span
                aria-live="polite"
                aria-label={`${value} ${label}`}
                className={cn(
                    'text-center font-semibold tabular-nums',
                    compact ? 'w-4 text-xs' : 'w-6 text-base',
                )}
            >
                {value}
            </span>
            <button
                type="button"
                onClick={() => onChange(value + 1)}
                disabled={value >= max}
                aria-label={`More ${label}`}
                className={buttonClass}
            >
                <Plus className={iconClass} />
            </button>
        </div>
    );
}

function SectionHeading({
    title,
    description,
    children,
}: {
    title: string;
    description: string;
    children?: ReactNode;
}) {
    return (
        <div
            className={cn(
                'flex flex-col gap-4 border-b pb-5 sm:flex-row sm:items-start sm:justify-between',
                dividerClass,
            )}
        >
            <div>
                <h2 className="text-xl font-semibold sm:text-2xl">{title}</h2>
                <p className="mt-1 text-sm text-navy/70 dark:text-white/70">
                    {description}
                </p>
            </div>
            {children}
        </div>
    );
}

export default function BookingDetails({
    trip,
    vehicle,
    contact,
}: Props) {
    const [forGuest, setForGuest] = useState(false);
    const [name, setName] = useState(contact.name);
    const [email, setEmail] = useState(contact.email);
    const [phone, setPhone] = useState(contact.phone);
    const [flight, setFlight] = useState(contact.flight);
    const [flightOrigin, setFlightOrigin] = useState('');
    const [adults, setAdults] = useState(
        Math.max(1, Math.min(trip.passengers, vehicle.passengers)),
    );
    const [seats, setSeats] = useState<Record<ChildSeat, number>>({
        child: 0,
        booster: 0,
        infant: 0,
    });
    const [bags, setBags] = useState(Math.min(trip.bags, vehicle.bags));
    const [carryOn, setCarryOn] = useState(0);
    const [oversized, setOversized] = useState(false);
    const [errors, setErrors] = useState<Errors>({});
    const [processing, setProcessing] = useState(false);

    const pickup = trip.pickup_at ? parsePickup(trip.pickup_at) : null;
    const arrival =
        pickup && trip.estimate
            ? new Date(
                  pickup.getTime() + trip.estimate.duration_minutes * 60_000,
              )
            : null;
    const seatsLeft = vehicle.passengers - adults - childSeatTotal(seats);
    const isAirport = trip.service.toLowerCase().includes('airport');
    const title = trip.destination
        ? `${trip.pickup} to ${trip.destination}`
        : trip.pickup;
    const ExtraIcon = vehicle.extra ? vehicleIcon(vehicle.extra.icon) : null;

    const switchTraveler = (guest: boolean) => {
        setForGuest(guest);
        setName(guest ? '' : contact.name);
        setEmail(guest ? '' : contact.email);
        setPhone(guest ? '' : contact.phone);
    };

    const submit = () => {
        router.put(
            '/booking/details',
            {
                contact_name: name,
                contact_email: email,
                contact_phone: phone || null,
                flight_details: flight || null,
                flight_origin: flightOrigin || null,
                adults,
                bags,
                carry_on_bags: carryOn,
                child_seats: seats,
                oversized_luggage: oversized,
            },
            {
                onStart: () => setProcessing(true),
                onFinish: () => setProcessing(false),
                onError: (validationErrors) => {
                    setErrors(validationErrors);

                },
            },
        );
    };

    return (
        <>
            <Head title="Booking Summary" />
            <div className="min-h-screen bg-mist font-google text-navy dark:bg-ink dark:text-white">
                <SiteHeader variant="solid" />

                <main className="mx-auto max-w-7xl px-4 pt-10 pb-20 sm:px-6 lg:px-10 lg:pt-16">
                    <PageIntro
                        title="Booking Summary"
                        breadcrumbs={['Booking', title]}
                    />

                    <form
                        onSubmit={(event) => {
                            event.preventDefault();
                            submit();
                        }}
                        className="mt-10 grid items-start gap-6 lg:grid-cols-[minmax(0,1fr)_360px]"
                    >
                        <div className="space-y-4">
                            <section className={cn(cardClass, 'p-5 sm:p-7')}>
                                <SectionHeading
                                    title="Lead Passenger Information"
                                    description="Details will be used for driver pickup communication and booking confirmation."
                                >
                                    <div
                                        role="radiogroup"
                                        aria-label="Who is traveling"
                                        className="flex w-fit shrink-0 rounded-lg bg-gray-100 p-1 text-xs font-semibold dark:bg-ink"
                                    >
                                        {[
                                            {
                                                guest: false,
                                                label: "I'm traveling",
                                            },
                                            {
                                                guest: true,
                                                label: 'Booking for a guest',
                                            },
                                        ].map((option) => (
                                            <button
                                                key={option.label}
                                                type="button"
                                                role="radio"
                                                aria-checked={
                                                    forGuest === option.guest
                                                }
                                                onClick={() =>
                                                    switchTraveler(option.guest)
                                                }
                                                className={cn(
                                                    'rounded-md px-3.5 py-2 transition-colors',
                                                    forGuest === option.guest
                                                        ? 'bg-white shadow-sm dark:bg-ocean'
                                                        : 'text-navy/70 hover:text-navy dark:text-white/70 dark:hover:text-white',
                                                )}
                                            >
                                                {option.label}
                                            </button>
                                        ))}
                                    </div>
                                </SectionHeading>

                                <div className="mt-6 grid gap-5 sm:grid-cols-2">
                                    <Field
                                        id="contact_name"
                                        label={
                                            forGuest
                                                ? "Guest's Full Name"
                                                : 'Full Name'
                                        }
                                        error={errors.contact_name}
                                        icon={<UserRound className="size-4" />}
                                    >
                                        <TextInput
                                            id="contact_name"
                                            withIcon
                                            value={name}
                                            onChange={(event) =>
                                                setName(event.target.value)
                                            }
                                            placeholder="Sarah Jenkins"
                                            autoComplete={
                                                forGuest ? 'off' : 'name'
                                            }
                                            required
                                        />
                                    </Field>
                                    <Field
                                        id="contact_email"
                                        label="Email Address"
                                        error={errors.contact_email}
                                        icon={<Mail className="size-4" />}
                                    >
                                        <TextInput
                                            id="contact_email"
                                            type="email"
                                            withIcon
                                            value={email}
                                            onChange={(event) =>
                                                setEmail(event.target.value)
                                            }
                                            placeholder="you@example.com"
                                            autoComplete={
                                                forGuest ? 'off' : 'email'
                                            }
                                            required
                                        />
                                    </Field>
                                    <div className="sm:col-span-2">
                                        <Field
                                            id="contact_phone"
                                            label="Mobile Phone Number"
                                            error={errors.contact_phone}
                                            icon={<Phone className="size-4" />}
                                        >
                                            <TextInput
                                                id="contact_phone"
                                                type="tel"
                                                withIcon
                                                value={phone}
                                                onChange={(event) =>
                                                    setPhone(event.target.value)
                                                }
                                                placeholder="+1 (555) 234-8900"
                                                autoComplete={
                                                    forGuest ? 'off' : 'tel'
                                                }
                                            />
                                        </Field>
                                    </div>
                                </div>

                                {isAirport && (
                                    <div className="mt-6 rounded-xl border border-navy/15 p-4 sm:p-5 dark:border-white/20">
                                        <div className="flex flex-col gap-1 sm:flex-row sm:items-center sm:justify-between">
                                            <h3 className="flex items-center gap-2 font-semibold">
                                                <Plane className="size-4 text-blue-700 dark:text-white" />
                                                Flight Details
                                            </h3>
                                            <p className="text-xs text-navy/70 dark:text-white/70">
                                                Your driver tracks your flight
                                                for delays
                                            </p>
                                        </div>
                                        <div className="mt-4 grid gap-4 sm:grid-cols-2">
                                            <Field
                                                id="flight_details"
                                                label="Flight Number"
                                                error={errors.flight_details}
                                            >
                                                <TextInput
                                                    id="flight_details"
                                                    value={flight}
                                                    onChange={(event) =>
                                                        setFlight(
                                                            event.target.value,
                                                        )
                                                    }
                                                    placeholder="Delta Airlines DL 412"
                                                />
                                            </Field>
                                            <Field
                                                id="flight_origin"
                                                label="Departure City / Airport"
                                                error={errors.flight_origin}
                                            >
                                                <TextInput
                                                    id="flight_origin"
                                                    value={flightOrigin}
                                                    onChange={(event) =>
                                                        setFlightOrigin(
                                                            event.target.value,
                                                        )
                                                    }
                                                    placeholder="London Heathrow (LHR)"
                                                />
                                            </Field>
                                        </div>
                                    </div>
                                )}
                            </section>

                            <section className={cn(cardClass, 'p-5 sm:p-7')}>
                                <SectionHeading
                                    title="Passengers & Seating"
                                    description="Specify passenger count and request complimentary child safety seats if needed."
                                />

                                <div
                                    className={cn(
                                        'flex items-center justify-between gap-4 border-b py-5',
                                        dividerClass,
                                    )}
                                >
                                    <div>
                                        <h3 className="font-semibold">
                                            Adult Passengers
                                        </h3>
                                        <p className="mt-0.5 text-xs text-navy/70 dark:text-white/70">
                                            Ages 12 and above (max{' '}
                                            {vehicle.passengers} in{' '}
                                            {vehicle.name}, including children)
                                        </p>
                                    </div>
                                    <Stepper
                                        label="adult passengers"
                                        value={adults}
                                        min={1}
                                        max={adults + seatsLeft}
                                        onChange={setAdults}
                                    />
                                </div>
                                <InputError
                                    message={errors.adults}
                                    className="mt-2"
                                />

                                <div className="pt-5">
                                    <h3 className="font-semibold">
                                        Complimentary Child Seats
                                    </h3>
                                    <p className="mt-0.5 text-xs text-navy/70 dark:text-white/70">
                                        Provided free of charge upon request.
                                        Each child counts toward the vehicle's
                                        seats.
                                    </p>
                                    <div className="mt-4 grid gap-3 sm:grid-cols-3">
                                        {childSeats.map((seat) => (
                                            <div
                                                key={seat.id}
                                                className="rounded-xl border border-navy/15 p-4 dark:border-white/20"
                                            >
                                                <p className="text-sm font-semibold">
                                                    {seat.name}
                                                </p>
                                                <p className="mt-1 text-xs text-navy/70 dark:text-white/70">
                                                    {seat.range}
                                                </p>
                                                <div className="mt-4 flex items-center justify-between">
                                                    <span className="text-[11px] font-semibold">
                                                        Quantity
                                                    </span>
                                                    <Stepper
                                                        compact
                                                        label={`${seat.name.toLowerCase()}s`}
                                                        value={seats[seat.id]}
                                                        max={
                                                            seats[seat.id] +
                                                            seatsLeft
                                                        }
                                                        onChange={(value) =>
                                                            setSeats(
                                                                (current) => ({
                                                                    ...current,
                                                                    [seat.id]:
                                                                        value,
                                                                }),
                                                            )
                                                        }
                                                    />
                                                </div>
                                            </div>
                                        ))}
                                    </div>
                                </div>
                            </section>

                            <section className={cn(cardClass, 'p-5 sm:p-7')}>
                                <SectionHeading
                                    title="Luggage Details"
                                    description={`Standard allowance for ${vehicle.name} is up to ${vehicle.bags} checked bags and one carry-on per passenger.`}
                                />

                                <div className="mt-5 grid gap-3 md:grid-cols-2">
                                    {[
                                        {
                                            id: 'bags',
                                            icon: Luggage,
                                            name: 'Checked Luggage',
                                            hint: 'Standard size up to 23 kg (50 lbs)',
                                            value: bags,
                                            max: vehicle.bags,
                                            onChange: setBags,
                                        },
                                        {
                                            id: 'carry_on_bags',
                                            icon: BriefcaseBusiness,
                                            name: 'Carry-on Bags',
                                            hint: 'Trolley or executive backpack',
                                            value: carryOn,
                                            max: vehicle.passengers,
                                            onChange: setCarryOn,
                                        },
                                    ].map((item) => (
                                        <div key={item.id}>
                                            <div className="flex items-center justify-between gap-3 rounded-xl border border-navy/15 p-4 dark:border-white/20">
                                                <div className="min-w-0">
                                                    <p className="flex items-center gap-2 font-semibold">
                                                        <item.icon className="size-4 text-blue-700 dark:text-white" />
                                                        {item.name}
                                                    </p>
                                                    <p className="mt-1 text-xs text-navy/70 dark:text-white/70">
                                                        {item.hint}
                                                    </p>
                                                </div>
                                                <Stepper
                                                    label={item.name.toLowerCase()}
                                                    value={item.value}
                                                    max={item.max}
                                                    onChange={item.onChange}
                                                />
                                            </div>
                                            <InputError
                                                message={errors[item.id]}
                                                className="mt-1 text-xs"
                                            />
                                        </div>
                                    ))}
                                </div>

                                <div className="mt-4 flex items-center justify-between gap-4 rounded-xl border border-navy/15 p-4 dark:border-white/20">
                                    <div>
                                        <p className="text-sm font-semibold">
                                            Transporting Oversized Baggage?
                                        </p>
                                        <p className="mt-0.5 text-xs text-navy/70 dark:text-white/70">
                                            Golf clubs, ski equipment, musical
                                            instruments, or large boxes.
                                        </p>
                                    </div>
                                    <ToggleSwitch
                                        checked={oversized}
                                        onChange={setOversized}
                                        label="Transporting oversized baggage"
                                    />
                                </div>
                            </section>

                            <InputError
                                message={errors.pickup_at ?? errors.timezone}
                            />

                            <div className="flex items-center justify-between gap-4 pt-2">
                                <Link
                                    href={vehicles()}
                                    className="flex items-center gap-2 rounded-lg border border-navy/15 bg-white px-5 py-3 text-sm font-semibold transition-colors hover:border-gold dark:border-white/30 dark:bg-transparent"
                                >
                                    <ArrowLeft className="size-4" />
                                    Back
                                </Link>
                                <button
                                    type="submit"
                                    disabled={processing}
                                    className="flex items-center gap-2 rounded-lg bg-gold px-8 py-3 text-sm font-semibold text-white transition-colors hover:bg-gold-dark disabled:opacity-60 sm:px-10"
                                >
                                    Continue to Special Requests
                                    <ArrowRight className="size-4" />
                                </button>
                            </div>
                        </div>

                        <aside
                            className={cn(
                                cardClass,
                                'overflow-hidden lg:sticky lg:top-6',
                            )}
                        >
                            <div className="relative aspect-[16/9] bg-gray-100">
                                <img
                                    src={vehicle.image}
                                    alt={vehicle.name}
                                    className="size-full object-cover"
                                />
                                <div className="absolute inset-0 bg-gradient-to-t from-navy/85 via-navy/20 to-transparent" />
                                <span className="absolute top-3 left-3 rounded bg-navy px-2.5 py-1 text-xs font-semibold text-white">
                                    {vehicle.class_name}
                                </span>
                                <div className="absolute inset-x-3 bottom-3 flex items-end justify-between gap-3 text-white">
                                    <div className="min-w-0">
                                        <p className="text-lg leading-tight font-semibold">
                                            {vehicle.name}
                                        </p>
                                        <p className="mt-0.5 truncate text-xs text-white/80">
                                            {vehicle.models}
                                        </p>
                                    </div>
                                    <span className="flex shrink-0 items-center gap-1 rounded bg-white/15 px-2 py-1 text-xs font-semibold backdrop-blur">
                                        <Star className="size-3 fill-gold text-gold" />
                                        {vehicle.rating}
                                    </span>
                                </div>
                            </div>

                            <div className="p-5">
                                <div
                                    className={cn(
                                        'flex flex-wrap gap-x-5 gap-y-2 border-b pb-4 text-xs font-medium',
                                        dividerClass,
                                    )}
                                >
                                    <span className="flex items-center gap-1.5">
                                        <Users className="size-3.5 text-blue-700 dark:text-white" />
                                        Up to {vehicle.passengers}
                                    </span>
                                    <span className="flex items-center gap-1.5">
                                        <Luggage className="size-3.5 text-blue-700 dark:text-white" />
                                        {vehicle.bags} bags
                                    </span>
                                    {vehicle.extra && ExtraIcon && (
                                        <span className="flex items-center gap-1.5">
                                            <ExtraIcon className="size-3.5 text-blue-700 dark:text-white" />
                                            {vehicle.extra.label}
                                        </span>
                                    )}
                                </div>

                                <p className="mt-5 text-xs font-semibold tracking-wider uppercase">
                                    Transfer Summary
                                </p>
                                <ol className="relative mt-4 space-y-5 before:absolute before:top-2 before:bottom-6 before:left-[5px] before:w-px before:bg-navy/15 dark:before:bg-white/20">
                                    <li className="relative flex gap-3">
                                        <span className="mt-1 size-[11px] shrink-0 rounded-full bg-navy ring-4 ring-white dark:bg-white dark:ring-ocean" />
                                        <div className="min-w-0">
                                            <p className="text-sm font-semibold">
                                                {pickup
                                                    ? `${formatTime(pickup)} · ${formatDay(pickup)}`
                                                    : 'Pickup'}
                                            </p>
                                            <p className="mt-0.5 text-xs text-navy/70 dark:text-white/70">
                                                {trip.pickup}
                                            </p>
                                        </div>
                                    </li>
                                    {(trip.destination || trip.hours) && (
                                        <li className="relative flex gap-3">
                                            <span className="mt-1 size-[11px] shrink-0 rounded-full bg-blue-700 ring-4 ring-white dark:bg-gold dark:ring-ocean" />
                                            <div className="min-w-0">
                                                <p className="text-sm font-semibold">
                                                    {trip.hours
                                                        ? `${trip.hours} hours chauffeur hire`
                                                        : arrival
                                                          ? `~${formatTime(arrival)} (Estimated)`
                                                          : 'Drop-off'}
                                                </p>
                                                {trip.destination && (
                                                    <p className="mt-0.5 text-xs text-navy/70 dark:text-white/70">
                                                        {trip.destination}
                                                    </p>
                                                )}
                                            </div>
                                        </li>
                                    )}
                                </ol>

                                <ul className="mt-5 space-y-2.5 rounded-xl bg-[#fbf8f2] p-4 dark:bg-white/10">
                                    {vehicle.features.map((feature) => (
                                        <li
                                            key={feature}
                                            className="flex items-start gap-2.5 text-xs"
                                        >
                                            <Check className="mt-px size-3.5 shrink-0 text-green-600 dark:text-green-400" />
                                            {feature}
                                        </li>
                                    ))}
                                </ul>

                                <dl
                                    className={cn(
                                        'mt-5 space-y-2.5 border-b pb-5 text-sm',
                                        dividerClass,
                                    )}
                                >
                                    <div className="flex justify-between gap-4">
                                        <dt className="text-navy/70 dark:text-white/70">
                                            {trip.estimate
                                                ? `Chauffeur fare (${trip.estimate.distance})`
                                                : 'Chauffeur fare'}
                                        </dt>
                                        <dd>{vehicle.price}</dd>
                                    </div>
                                    <div className="flex justify-between gap-4">
                                        <dt className="text-navy/70 dark:text-white/70">
                                            Taxes, tolls &amp; gratuity
                                        </dt>
                                        <dd className="text-green-700 dark:text-green-400">
                                            Included
                                        </dd>
                                    </div>
                                    <div className="flex justify-between gap-4">
                                        <dt className="text-navy/70 dark:text-white/70">
                                            Child seats
                                        </dt>
                                        <dd className="text-green-700 dark:text-green-400">
                                            Free
                                        </dd>
                                    </div>
                                </dl>

                                <div className="mt-5 flex items-end justify-between gap-4">
                                    <div>
                                        <p className="text-xl font-semibold">
                                            Total Fare
                                        </p>
                                        <p className="mt-0.5 text-[11px] font-semibold text-navy/70 dark:text-white/70">
                                            All taxes, tolls &amp; driver tip
                                            included
                                        </p>
                                    </div>
                                    <p className="text-3xl font-semibold">
                                        {vehicle.price}
                                    </p>
                                </div>
                            </div>
                        </aside>
                    </form>
                </main>

                <SiteFooter className="bg-mist dark:bg-ink" />
            </div>
        </>
    );
}
