import { Head, Link, router, usePage } from '@inertiajs/react';
import dayGridPlugin from '@fullcalendar/daygrid';
import interactionPlugin from '@fullcalendar/interaction';
import FullCalendar from '@fullcalendar/react';
import timeGridPlugin from '@fullcalendar/timegrid';
import {
    CalendarCheck,
    CalendarClock,
    CalendarDays,
    ChevronLeft,
    ChevronRight,
    CircleDollarSign,
    CircleX,
    Clock,
    LayoutList,
    MapPin,
    Plus,
    RefreshCw,
    Search,
    Sparkles,
    Wallet,
    X,
} from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';
import {
    AdminBookingEditDrawer,
} from '@/components/booking/admin-booking-edit-drawer';
import type {
    AddonOption,
    LocationOption,
    PackageOption,
    TechnicianOption,
} from '@/components/booking/admin-booking-edit-drawer';
import { AdminBookingPaymentActions } from '@/components/booking/admin-booking-payment-actions';
import { AdminWalkInBookingDrawer } from '@/components/booking/admin-walk-in-booking-drawer';
import { BookingDetailPanel } from '@/components/booking/booking-detail-panel';
import type { BookingDetail } from '@/components/booking/booking-detail-panel';
import { FormDrawer } from '@/components/layout/form-drawer';
import { PageHeader } from '@/components/layout/page-header';
import { ResourceActionsMenu } from '@/components/resource-actions-menu';
import { StatusBadge } from '@/components/status-badge';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Button } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import {
    Combobox,
    ComboboxContent,
    ComboboxEmpty,
    ComboboxInput,
    ComboboxItem,
    ComboboxList,
} from '@/components/ui/combobox';
import { SheetFooter } from '@/components/ui/sheet';
import {
    InputGroup,
    InputGroupAddon,
    InputGroupButton,
    InputGroupInput,
} from '@/components/ui/input-group';
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
import AppLayout from '@/layouts/app-layout';
import adminBookings from '@/routes/admin/bookings';
import adminCustomers from '@/routes/admin/customers';

type BookingRow = BookingDetail & {
    technician_id: number | null;
    location_id: number | null;
    package_id: number;
    amount_paid: number;
    addons_total: number;
    is_recurring: boolean;
    stripe_payment_intent_id?: string | null;
};

type BookingStats = {
    today: number;
    upcoming: number;
    completed: number;
    revenue_cents: number;
    unpaid_cents: number;
};

type VehicleSizeOption = {
    id: number;
    slug: string;
    name: string;
};

type CustomerVehicleOption = {
    id: number;
    make: string;
    model: string;
    year: number;
    color: string | null;
    size: string;
    is_default: boolean;
    label: string;
};

type CustomerOption = {
    id: number;
    name: string;
    email: string;
    phone: string | null;
    office_suite: string | null;
    cell: string | null;
    vehicles: CustomerVehicleOption[];
};

type Props = {
    bookings: BookingRow[];
    stats: BookingStats;
    customerOptions: CustomerOption[];
    technicians: TechnicianOption[];
    locations: LocationOption[];
    packages: PackageOption[];
    addons: AddonOption[];
    vehicleSizeCategories: VehicleSizeOption[];
    stripeEnabled: boolean;
    stripePublishableKey: string | null;
};

function formatMoney(cents: number): string {
    return new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: 'USD',
        minimumFractionDigits: 2,
        maximumFractionDigits: 2,
    }).format(cents / 100);
}

export default function AdminBookingsIndex({
    bookings,
    stats,
    customerOptions,
    technicians,
    locations,
    packages,
    addons,
    vehicleSizeCategories,
    stripeEnabled,
    stripePublishableKey,
}: Props) {
    const page = usePage();
    const { flash } = page.props as {
        flash?: {
            success?: string | null;
            error?: string | null;
            charge_booking_id?: number | null;
        };
    };
    const openedBookingFromQueryRef = useRef<string | null>(null);
    const openedEditFromQueryRef = useRef<string | null>(null);
    const [successMessage, setSuccessMessage] = useState<string | null>(null);

    useEffect(() => {
        if (flash?.success) {
            setSuccessMessage(flash.success);
        }
    }, [flash?.success]);

    useEffect(() => {
        const chargeBookingId = flash?.charge_booking_id;

        if (!chargeBookingId) {
            return;
        }

        const booking = bookings.find((item) => item.id === chargeBookingId);

        if (booking) {
            setViewingBooking(booking);
        }
    }, [flash?.charge_booking_id, bookings]);

    const [viewMode, setViewMode] = useState<'list' | 'calendar'>(() => {
        try {
            return (localStorage.getItem('admin-bookings-view') as 'list' | 'calendar') ?? 'list';
        } catch {
            return 'list';
        }
    });

    const switchView = useCallback((mode: 'list' | 'calendar') => {
        setViewMode(mode);
        try { localStorage.setItem('admin-bookings-view', mode); } catch { /* ignore */ }
    }, []);

    const [activeTab, setActiveTab] = useState<'upcoming' | 'unconfirmed' | 'recurring' | 'past' | 'canceled'>('upcoming');
    const [search, setSearch] = useState('');
    const [selectedLocationId, setSelectedLocationId] = useState<number | null>(null);
    const [currentPage, setCurrentPage] = useState(1);

    const [viewingBooking, setViewingBooking] = useState<BookingRow | null>(
        null,
    );
    const [editingBooking, setEditingBooking] = useState<BookingRow | null>(
        null,
    );
    const [walkInOpen, setWalkInOpen] = useState(false);
    const defaultLocationId = locations[0]?.id ?? null;

    const openView = (booking: BookingRow) => {
        setViewingBooking(booking);
    };

    const closeView = () => {
        setViewingBooking(null);
        openedBookingFromQueryRef.current = null;

        const pageUrl = new URL(
            page.url,
            typeof window !== 'undefined'
                ? window.location.origin
                : 'http://localhost',
        );

        if (!pageUrl.searchParams.has('booking')) {
            return;
        }

        pageUrl.searchParams.delete('booking');
        const nextUrl =
            pageUrl.pathname +
            (pageUrl.searchParams.toString()
                ? `?${pageUrl.searchParams.toString()}`
                : '');

        router.get(nextUrl, {}, { preserveState: true, replace: true });
    };

    useEffect(() => {
        const pageUrl = new URL(
            page.url,
            typeof window !== 'undefined'
                ? window.location.origin
                : 'http://localhost',
        );
        const bookingId = pageUrl.searchParams.get('booking');
        const editId = pageUrl.searchParams.get('edit');

        if (editId) {
            if (openedEditFromQueryRef.current === editId) {
                return;
            }

            const booking = bookings.find(
                (row) => row.id === Number.parseInt(editId, 10),
            );

            if (!booking) {
                return;
            }

            openedEditFromQueryRef.current = editId;
            openEdit(booking);

            return;
        }

        if (!bookingId || openedBookingFromQueryRef.current === bookingId) {
            return;
        }

        const booking = bookings.find(
            (row) => row.id === Number.parseInt(bookingId, 10),
        );

        if (!booking) {
            return;
        }

        openedBookingFromQueryRef.current = bookingId;
        setViewingBooking(booking);
    }, [page.url, bookings]);

    useEffect(() => {
        if (!viewingBooking) {
            return;
        }

        const fresh = bookings.find((row) => row.id === viewingBooking.id);

        if (!fresh) {
            return;
        }

        if (
            fresh.payment_status !== viewingBooking.payment_status
            || fresh.amount_paid !== viewingBooking.amount_paid
            || fresh.stripe_payment_intent_id !== viewingBooking.stripe_payment_intent_id
        ) {
            setViewingBooking(fresh);
        }
    }, [bookings, viewingBooking]);

    const openEdit = (booking: BookingRow) => {
        setEditingBooking(booking);
    };

    const openEditFromView = () => {
        if (!viewingBooking) {
            return;
        }

        const booking = viewingBooking;
        closeView();
        openEdit(booking);
    };

    const closeEdit = () => {
        setEditingBooking(null);
        openedEditFromQueryRef.current = null;

        const pageUrl = new URL(
            page.url,
            typeof window !== 'undefined'
                ? window.location.origin
                : 'http://localhost',
        );

        if (!pageUrl.searchParams.has('edit')) {
            return;
        }

        pageUrl.searchParams.delete('edit');
        const nextUrl =
            pageUrl.pathname +
            (pageUrl.searchParams.toString()
                ? `?${pageUrl.searchParams.toString()}`
                : '');

        router.get(nextUrl, {}, { preserveState: true, replace: true });
    };

    const cancelBooking = (bookingId: number) => {
        router.delete(adminBookings.destroy.url({ booking: bookingId }), {
            data: {
                reason: 'admin_cancelled',
            },
        });
    };

    const ITEMS_PER_PAGE = 10;

    const now = new Date();

    const locationFilteredBookings = selectedLocationId === null
        ? bookings
        : bookings.filter((b) => b.location_id === selectedLocationId);

    const tabFilteredBookings = locationFilteredBookings.filter((b) => {
        const scheduledAt = new Date(b.scheduled_at);
        switch (activeTab) {
            case 'upcoming':
                return scheduledAt >= now && !['cancelled', 'no_show', 'completed'].includes(b.service_status);
            case 'unconfirmed':
                return b.payment_status === 'pending' && !['cancelled', 'no_show', 'arrived', 'in_progress', 'completed'].includes(b.service_status);
            case 'recurring':
                return b.is_recurring === true;
            case 'past':
                return scheduledAt < now && ['completed', 'no_show'].includes(b.service_status);
            case 'canceled':
                return b.service_status === 'cancelled';
        }
    });

    const q = search.trim().toLowerCase();
    const filteredBookings = q
        ? tabFilteredBookings.filter((b) =>
              [
                  b.uuid,
                  b.customer?.name,
                  b.package?.name,
                  b.vehicle ? `${b.vehicle.year} ${b.vehicle.make} ${b.vehicle.model}` : '',
              ]
                  .filter(Boolean)
                  .some((field) => field!.toLowerCase().includes(q)),
          )
        : tabFilteredBookings;

    const totalPages = Math.max(1, Math.ceil(filteredBookings.length / ITEMS_PER_PAGE));
    const paginatedBookings = filteredBookings.slice(
        (currentPage - 1) * ITEMS_PER_PAGE,
        currentPage * ITEMS_PER_PAGE,
    );

    const TAB_COUNTS = {
        upcoming: locationFilteredBookings.filter((b) => new Date(b.scheduled_at) >= now && !['cancelled', 'no_show', 'completed'].includes(b.service_status)).length,
        unconfirmed: locationFilteredBookings.filter((b) => b.payment_status === 'pending' && !['cancelled', 'no_show', 'arrived', 'in_progress', 'completed'].includes(b.service_status)).length,
        recurring: locationFilteredBookings.filter((b) => b.is_recurring).length,
        past: locationFilteredBookings.filter((b) => new Date(b.scheduled_at) < now && ['completed', 'no_show'].includes(b.service_status)).length,
        canceled: locationFilteredBookings.filter((b) => b.service_status === 'cancelled').length,
    };

    return (
        <>
            <Head title="Admin bookings" />
            <div className="flex h-full flex-1 flex-col gap-6">
                {successMessage ? (
                    <Alert>
                        <AlertDescription>{successMessage}</AlertDescription>
                    </Alert>
                ) : null}

                <PageHeader
                    title="Bookings"
                    description="Manage appointments, walk-ins, and service status."
                    actions={
                        <div className="flex flex-wrap items-center gap-2">
                            <Button
                                size="sm"
                                onClick={() => setWalkInOpen(true)}
                            >
                                <Plus className="size-4" />
                                New walk-in booking
                            </Button>
                            <div className="flex items-center rounded-md border">
                                <Button
                                    variant={viewMode === 'list' ? 'secondary' : 'ghost'}
                                    size="icon"
                                    className="size-8 rounded-r-none border-0"
                                    onClick={() => switchView('list')}
                                    title="List view"
                                >
                                    <LayoutList className="size-4" />
                                </Button>
                                <Button
                                    variant={viewMode === 'calendar' ? 'secondary' : 'ghost'}
                                    size="icon"
                                    className="size-8 rounded-l-none border-0 border-l"
                                    onClick={() => switchView('calendar')}
                                    title="Calendar view"
                                >
                                    <CalendarDays className="size-4" />
                                </Button>
                            </div>
                        </div>
                    }
                />

                <div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-5">
                    <Card size="sm">
                        <CardHeader>
                            <CardDescription>Today</CardDescription>
                            <CardTitle>{stats.today}</CardTitle>
                        </CardHeader>
                        <CardContent className="flex items-center gap-2 text-muted-foreground">
                            <CalendarCheck className="size-4" />
                            <span className="text-xs">Scheduled today</span>
                        </CardContent>
                    </Card>
                    <Card size="sm">
                        <CardHeader>
                            <CardDescription>Upcoming</CardDescription>
                            <CardTitle>{stats.upcoming}</CardTitle>
                        </CardHeader>
                        <CardContent className="flex items-center gap-2 text-muted-foreground">
                            <CalendarClock className="size-4" />
                            <span className="text-xs">Future appointments</span>
                        </CardContent>
                    </Card>
                    <Card size="sm">
                        <CardHeader>
                            <CardDescription>Completed</CardDescription>
                            <CardTitle>{stats.completed}</CardTitle>
                        </CardHeader>
                        <CardContent className="flex items-center gap-2 text-muted-foreground">
                            <Sparkles className="size-4" />
                            <span className="text-xs">Finished washes</span>
                        </CardContent>
                    </Card>
                    <Card size="sm">
                        <CardHeader>
                            <CardDescription>Revenue</CardDescription>
                            <CardTitle>{formatMoney(stats.revenue_cents)}</CardTitle>
                        </CardHeader>
                        <CardContent className="flex items-center gap-2 text-muted-foreground">
                            <CircleDollarSign className="size-4" />
                            <span className="text-xs">Collected payments</span>
                        </CardContent>
                    </Card>
                    <Card size="sm">
                        <CardHeader>
                            <CardDescription>Unpaid</CardDescription>
                            <CardTitle>{formatMoney(stats.unpaid_cents)}</CardTitle>
                        </CardHeader>
                        <CardContent className="flex items-center gap-2 text-muted-foreground">
                            <Wallet className="size-4" />
                            <span className="text-xs">Outstanding balance</span>
                        </CardContent>
                    </Card>
                </div>

                {viewMode === 'list' ? (
                    <div className="rounded-xl border bg-card shadow-sm">
                        {/* Tabs header */}
                        <div className="flex items-center justify-between gap-4 border-b px-4 py-2">
                            <Tabs
                                value={activeTab}
                                onValueChange={(v) => {
                                    setActiveTab(v as typeof activeTab);
                                    setCurrentPage(1);
                                }}
                            >
                                <TabsList>
                                    {(
                                        [
                                            ['upcoming',    'Upcoming',    CalendarClock],
                                            ['unconfirmed', 'Unconfirmed', Clock],
                                            ['recurring',   'Recurring',   RefreshCw],
                                            ['past',        'Past',        CalendarCheck],
                                            ['canceled',    'Canceled',    CircleX],
                                        ] as const
                                    ).map(([key, label, Icon]) => (
                                        <TabsTrigger key={key} value={key}>
                                            <Icon />
                                            {label}
                                            {TAB_COUNTS[key] > 0 && (
                                                <span className="rounded-full bg-background/60 px-1.5 py-0.5 text-[10px] font-medium tabular-nums">
                                                    {TAB_COUNTS[key]}
                                                </span>
                                            )}
                                        </TabsTrigger>
                                    ))}
                                </TabsList>
                            </Tabs>
                            <div className="flex items-center gap-2">
                                {locations.length > 1 && (
                                    <Combobox
                                        items={locations}
                                        itemToStringLabel={(loc: LocationOption) => loc.name}
                                        itemToStringValue={(loc: LocationOption) => String(loc.id)}
                                        isItemEqualToValue={(a, b) => a?.id === b?.id}
                                        value={locations.find((l) => l.id === selectedLocationId) ?? null}
                                        onValueChange={(val) => {
                                            setSelectedLocationId((val as LocationOption | null)?.id ?? null);
                                            setCurrentPage(1);
                                        }}
                                    >
                                        <ComboboxInput
                                            showClear
                                            placeholder="All locations"
                                            className="h-8 w-44 text-sm"
                                        />
                                        <ComboboxContent>
                                            <ComboboxEmpty>No locations found.</ComboboxEmpty>
                                            <ComboboxList>
                                                {(loc: LocationOption) => (
                                                    <ComboboxItem key={loc.id} value={loc}>
                                                        {loc.name}
                                                    </ComboboxItem>
                                                )}
                                            </ComboboxList>
                                        </ComboboxContent>
                                    </Combobox>
                                )}
                                <InputGroup className="h-8 w-48">
                                    <InputGroupAddon align="inline-start">
                                        <Search className="size-3.5 text-muted-foreground" />
                                    </InputGroupAddon>
                                    <InputGroupInput
                                        className="text-sm"
                                        placeholder="Search bookings…"
                                        value={search}
                                        onChange={(e) => {
                                            setSearch(e.target.value);
                                            setCurrentPage(1);
                                        }}
                                    />
                                    {search && (
                                        <InputGroupAddon align="inline-end">
                                            <InputGroupButton
                                                size="icon-xs"
                                                variant="ghost"
                                                onClick={() => {
                                                    setSearch('');
                                                    setCurrentPage(1);
                                                }}
                                            >
                                                <X className="pointer-events-none" />
                                            </InputGroupButton>
                                        </InputGroupAddon>
                                    )}
                                </InputGroup>
                            </div>
                        </div>

                        {/* Booking cards */}
                        {filteredBookings.length === 0 ? (
                            <div className="px-6 py-12 text-center">
                                <p className="text-sm text-muted-foreground">No bookings in this category.</p>
                            </div>
                        ) : (
                            <div className="divide-y">
                                {paginatedBookings.map((booking) => {
                                    const d = new Date(booking.scheduled_at);
                                    const weekday = d.toLocaleDateString('en-US', { weekday: 'short' });
                                    const dayNum = d.getDate();
                                    const month = d.toLocaleDateString('en-US', { month: 'short' });
                                    const timeStr = d.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });
                                    const locationLabel =
                                        booking.service_type === 'fixed'
                                            ? (booking.location?.name ?? 'Fixed location')
                                            : booking.service_address
                                              ? `${booking.service_address}, ${booking.service_city ?? ''}`
                                              : 'Mobile service';

                                    return (
                                        <div
                                            key={booking.id}
                                            className="flex items-center gap-0 px-4 py-4 hover:bg-muted/30 transition-colors"
                                        >
                                            {/* Date block */}
                                            <div className="w-14 shrink-0 pr-4 text-center">
                                                <p className="text-[10px] font-medium uppercase text-muted-foreground">{weekday}</p>
                                                <p className="text-2xl font-bold leading-tight">{dayNum}</p>
                                                <p className="text-xs text-muted-foreground">{month}</p>
                                            </div>

                                            {/* Divider */}
                                            <div className="mr-4 w-px self-stretch bg-border" />

                                            {/* Time + location */}
                                            <div className="w-44 shrink-0 space-y-1 pt-0.5">
                                                <p className="text-xs font-semibold text-primary">
                                                    #{booking.uuid.slice(0, 8).toUpperCase()}
                                                </p>
                                                <div className="flex items-center gap-1.5 text-sm">
                                                    <Clock className="size-3.5 shrink-0 text-muted-foreground" />
                                                    <span>{timeStr}</span>
                                                </div>
                                                <div className="flex items-center gap-1.5 text-sm text-muted-foreground">
                                                    <MapPin className="size-3.5 shrink-0" />
                                                    <span className="truncate">{locationLabel}</span>
                                                </div>
                                                {booking.is_recurring && (
                                                    <div className="flex items-center gap-1.5 text-xs text-muted-foreground">
                                                        <RefreshCw className="size-3 shrink-0" />
                                                        <span>Recurring</span>
                                                    </div>
                                                )}
                                            </div>

                                            {/* Booking details */}
                                            <div className="min-w-0 flex-1 space-y-0.5">
                                                <p className="font-semibold">
                                                    {booking.package?.name ?? 'Car Wash'}
                                                </p>
                                                {booking.vehicle && (
                                                    <p className="text-sm text-muted-foreground">
                                                        {booking.vehicle.year} {booking.vehicle.make} {booking.vehicle.model}
                                                        {booking.vehicle.color ? ` · ${booking.vehicle.color}` : ''}
                                                    </p>
                                                )}
                                                {booking.customer && (
                                                    <p className="text-sm text-muted-foreground">
                                                        <Link
                                                            href={adminCustomers.show.url({ user: booking.customer.id })}
                                                            className="hover:underline"
                                                        >
                                                            {booking.customer.name}
                                                        </Link>
                                                        {booking.technician ? ` · Tech: ${booking.technician.name}` : ''}
                                                    </p>
                                                )}
                                            </div>

                                            {/* Status + actions */}
                                            <div className="ml-4 flex shrink-0 items-center gap-2">
                                                <StatusBadge status={booking.service_status} />
                                                <ResourceActionsMenu
                                                    onView={() => openView(booking)}
                                                    onEdit={() => openEdit(booking)}
                                                    onDelete={() => cancelBooking(booking.id)}
                                                    disableDelete={booking.service_status === 'cancelled'}
                                                    deleteLabel="Cancel booking"
                                                    deleteTitle="Cancel booking?"
                                                    deleteDescription="This marks the booking as cancelled. Payment records stay intact."
                                                    confirmLabel="Cancel booking"
                                                />
                                            </div>
                                        </div>
                                    );
                                })}
                            </div>
                        )}

                        {/* Pagination */}
                        {totalPages > 1 && (
                            <div className="flex items-center justify-between border-t px-4 py-3">
                                <p className="text-xs text-muted-foreground">
                                    {(currentPage - 1) * ITEMS_PER_PAGE + 1}–{Math.min(currentPage * ITEMS_PER_PAGE, filteredBookings.length)} of {filteredBookings.length} bookings
                                </p>
                                <div className="flex items-center gap-1">
                                    <Button
                                        variant="outline"
                                        size="icon"
                                        className="size-7"
                                        disabled={currentPage === 1}
                                        onClick={() => setCurrentPage((p) => p - 1)}
                                    >
                                        <ChevronLeft className="size-3.5" />
                                    </Button>
                                    <span className="min-w-16 text-center text-xs text-muted-foreground">
                                        {currentPage} / {totalPages}
                                    </span>
                                    <Button
                                        variant="outline"
                                        size="icon"
                                        className="size-7"
                                        disabled={currentPage === totalPages}
                                        onClick={() => setCurrentPage((p) => p + 1)}
                                    >
                                        <ChevronRight className="size-3.5" />
                                    </Button>
                                </div>
                            </div>
                        )}
                    </div>
                ) : (
                    <div className={[
                        'overflow-hidden rounded-xl border bg-background',
                        '[&_.fc]:font-sans!',
                        // toolbar
                        '[&_.fc-toolbar.fc-header-toolbar]:border-b! [&_.fc-toolbar.fc-header-toolbar]:border-border! [&_.fc-toolbar.fc-header-toolbar]:px-4! [&_.fc-toolbar.fc-header-toolbar]:py-3! [&_.fc-toolbar.fc-header-toolbar]:bg-background!',
                        '[&_.fc-toolbar-title]:text-sm! [&_.fc-toolbar-title]:font-semibold! [&_.fc-toolbar-title]:text-foreground!',
                        // nav buttons — ghost style, adapt to dark/light via design tokens
                        '[&_.fc-button]:border! [&_.fc-button]:border-border! [&_.fc-button]:bg-background! [&_.fc-button]:text-foreground! [&_.fc-button]:shadow-none! [&_.fc-button]:text-xs! [&_.fc-button]:font-medium! [&_.fc-button]:py-1! [&_.fc-button]:px-2.5! [&_.fc-button]:rounded-md! [&_.fc-button]:transition-colors! [&_.fc-button]:capitalize!',
                        '[&_.fc-button:hover]:bg-muted! [&_.fc-button:focus]:outline-none! [&_.fc-button:focus]:ring-0! [&_.fc-button:focus]:shadow-none!',
                        '[&_.fc-button-active]:bg-secondary! [&_.fc-button-active]:text-secondary-foreground! [&_.fc-button-active:hover]:bg-secondary/80!',
                        '[&_.fc-prev-button]:rounded-r-none! [&_.fc-next-button]:-ml-px! [&_.fc-next-button]:rounded-l-none!',
                        '[&_.fc-today-button]:rounded-md!',
                        // week/month view switcher — small gap so they read as separate controls
                        '[&_.fc-toolbar-chunk:last-child_.fc-button-group]:gap-1!',
                        // column headers
                        '[&_.fc-col-header-cell]:bg-card! [&_.fc-col-header-cell-cushion]:text-xs! [&_.fc-col-header-cell-cushion]:font-medium! [&_.fc-col-header-cell-cushion]:text-muted-foreground! [&_.fc-col-header-cell-cushion]:no-underline! [&_.fc-col-header-cell-cushion]:py-2! [&_.fc-col-header-cell-cushion]:block! [&_.fc-col-header-cell-cushion]:text-center!',
                        // cell backgrounds — use card token so it adapts to dark mode
                        '[&_.fc-daygrid-day]:bg-card! [&_.fc-timegrid-col]:bg-card! [&_.fc-timegrid-axis]:bg-card!',
                        // today — compound selectors beat the generic bg-card overrides above
                        '[&_.fc-col-header-cell.fc-day-today]:bg-primary/12! [&_.fc-col-header-cell.fc-day-today_.fc-col-header-cell-cushion]:text-primary!',
                        '[&_.fc-timegrid-col.fc-day-today]:bg-primary/8! [&_.fc-daygrid-day.fc-day-today]:bg-primary/8!',
                        // borders — use design system token
                        '[&_.fc-theme-standard_td]:border-border! [&_.fc-theme-standard_th]:border-border! [&_.fc-scrollgrid]:border-border!',
                        // time labels
                        '[&_.fc-timegrid-slot-label-cushion]:text-xs! [&_.fc-timegrid-slot-label-cushion]:text-muted-foreground! [&_.fc-timegrid-slot-label-cushion]:pr-3!',
                        '[&_.fc-timegrid-slot]:h-12!',
                        // weekends — compound selectors for column body + header, muted adapts to dark/light
                        '[&_.fc-col-header-cell.fc-day-sat]:bg-muted/60! [&_.fc-col-header-cell.fc-day-sun]:bg-muted/60!',
                        '[&_.fc-timegrid-col.fc-day-sat]:bg-muted/40! [&_.fc-timegrid-col.fc-day-sun]:bg-muted/40!',
                        '[&_.fc-daygrid-day.fc-day-sat]:bg-muted/40! [&_.fc-daygrid-day.fc-day-sun]:bg-muted/40!',
                        // now indicator — red dashed line + red arrow
                        '[&_.fc-now-indicator-line]:border-red-500! [&_.fc-now-indicator-line]:border-t-2! [&_.fc-now-indicator-line]:border-dashed!',
                        '[&_.fc-now-indicator-arrow]:border-l-red-500! [&_.fc-now-indicator-arrow]:border-t-transparent! [&_.fc-now-indicator-arrow]:border-b-transparent!',
                        // events — transparent shell so custom content fills it; pointer so they feel clickable
                        '[&_.fc-event]:shadow-none! [&_.fc-event]:border-0! [&_.fc-event-main]:p-0! [&_.fc-v-event]:bg-transparent! [&_.fc-h-event]:bg-transparent! [&_.fc-event]:cursor-pointer!',
                    ].join(' ')}>
                        <FullCalendar
                            plugins={[timeGridPlugin, dayGridPlugin, interactionPlugin]}
                            initialView="timeGridWeek"
                            headerToolbar={{
                                left: 'prev,next today',
                                center: 'title',
                                right: 'timeGridWeek,dayGridMonth',
                            }}
                            height="auto"
                            nowIndicator
                            slotMinTime="06:00:00"
                            slotMaxTime="22:00:00"
                            events="/admin/calendar/events"
                            eventClick={(arg) => {
                                const bookingId = parseInt(arg.event.id, 10);
                                const booking = bookings.find((b) => b.id === bookingId);

                                if (booking) {
                                    openView(booking);
                                }
                            }}
                            dayHeaderContent={(arg) => {
                                const num = String(arg.date.getDate()).padStart(2, '0');
                                const day = arg.date.toLocaleDateString('en-US', { weekday: 'short' }).toUpperCase();

                                return (
                                    <span>{num} {day}</span>
                                );
                            }}
                            eventContent={(arg) => {
                                const status = arg.event.extendedProps.status as string;
                                const cardMap: Record<string, string> = {
                                    scheduled:   'bg-blue-50   dark:bg-blue-950/70  border-blue-200   dark:border-blue-800  text-blue-900   dark:text-blue-200',
                                    arrived:     'bg-orange-50 dark:bg-orange-950/70 border-orange-200 dark:border-orange-800 text-orange-900 dark:text-orange-200',
                                    in_progress: 'bg-violet-50 dark:bg-violet-950/70 border-violet-200 dark:border-violet-800 text-violet-900 dark:text-violet-200',
                                    completed:   'bg-emerald-50 dark:bg-emerald-950/70 border-emerald-200 dark:border-emerald-800 text-emerald-900 dark:text-emerald-200',
                                    cancelled:   'bg-gray-100  dark:bg-gray-800/60  border-gray-200   dark:border-gray-700  text-gray-500   dark:text-gray-400',
                                    no_show:     'bg-gray-100  dark:bg-gray-800/60  border-gray-200   dark:border-gray-700  text-gray-500   dark:text-gray-400',
                                };
                                const cls = cardMap[status] ?? 'bg-indigo-50 dark:bg-indigo-950/70 border-indigo-200 dark:border-indigo-800 text-indigo-900 dark:text-indigo-200';

                                return (
                                    <div className={`${cls} border flex flex-col gap-0.5 rounded-md px-2 py-1.5 h-full overflow-hidden`}>
                                        <span className="truncate text-[11px] font-semibold leading-tight">
                                            {arg.event.title}
                                        </span>
                                        <span className="text-[10px] opacity-60 leading-tight">
                                            {arg.timeText}
                                        </span>
                                    </div>
                                );
                            }}
                        />
                    </div>
                )}
            </div>

            <FormDrawer
                open={viewingBooking !== null}
                onOpenChange={(open) => {
                    if (!open) {
                        closeView();
                    }
                }}
                title={`Booking #${viewingBooking?.uuid.slice(0, 8).toUpperCase() ?? ''}`}
                description={
                    viewingBooking?.customer
                        ? viewingBooking.customer.name
                        : 'Guest booking'
                }
                direction="right"
                className="w-full sm:max-w-lg"
            >
                {viewingBooking ? (
                    <BookingDetailPanel
                        booking={viewingBooking}
                        customerHref={
                            viewingBooking.customer
                                ? adminCustomers.show.url({
                                      user: viewingBooking.customer.id,
                                  })
                                : undefined
                        }
                        paymentActions={
                            <AdminBookingPaymentActions
                                booking={viewingBooking}
                                stripeEnabled={stripeEnabled}
                                stripePublishableKey={stripePublishableKey}
                                autoOpenCharge={flash?.charge_booking_id === viewingBooking.id}
                            />
                        }
                        footer={
                            <SheetFooter className="px-0 pb-0 sm:flex-row">
                                <Button
                                    type="button"
                                    variant="outline"
                                    onClick={closeView}
                                >
                                    Close
                                </Button>
                                <Button
                                    type="button"
                                    onClick={openEditFromView}
                                >
                                    Edit booking
                                </Button>
                            </SheetFooter>
                        }
                    />
                ) : null}
            </FormDrawer>

            <AdminWalkInBookingDrawer
                open={walkInOpen}
                onOpenChange={setWalkInOpen}
                customerOptions={customerOptions}
                technicians={technicians}
                locations={locations}
                packages={packages}
                addons={addons}
                vehicleSizeCategories={vehicleSizeCategories}
                stripeEnabled={stripeEnabled}
                defaultLocationId={defaultLocationId}
            />

            <AdminBookingEditDrawer
                open={editingBooking !== null}
                onOpenChange={(open) => {
                    if (!open) {
                        closeEdit();
                    }
                }}
                booking={editingBooking}
                technicians={technicians}
                locations={locations}
                packages={packages}
                addons={addons}
                stripeEnabled={stripeEnabled}
                stripePublishableKey={stripePublishableKey}
            />
        </>
    );
}

AdminBookingsIndex.layout = (page: React.ReactNode) => (
    <AppLayout
        breadcrumbs={[
            {
                title: 'Admin bookings',
                href: '/admin/bookings',
            },
        ]}
    >
        {page}
    </AppLayout>
);
