import { Form, Head } from '@inertiajs/react';
import { CalendarDays, CheckCircle2, ChevronLeft, ChevronRight, LayoutList, Calendar } from 'lucide-react';
import { useState } from 'react';
import { DateStrip } from '@/components/booking/date-strip';
import { TimeSlotGrid } from '@/components/booking/time-slot-grid';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs';
import {
    useBookingDateTimeFormatters,
    useBookingTimezone,
} from '@/hooks/use-booking-timezone';
import {
    bookingDateKeyFromDate,
    parseBookingScheduledAt,
    toBookingScheduledAt,
} from '@/lib/booking-timezones';
import { cn } from '@/lib/utils';

function formatTime(time: string): string {
    const [h, m] = time.split(':').map(Number);
    const period = h < 12 ? 'AM' : 'PM';
    const hour = h === 0 ? 12 : h > 12 ? h - 12 : h;

    return `${hour}:${String(m).padStart(2, '0')} ${period}`;
}

function formatOpenHoursLabel(times: Record<string, number>): string | null {
    const keys = Object.keys(times).sort();

    if (keys.length === 0) return null;

    const [lh, lm] = keys[keys.length - 1].split(':').map(Number);
    const closeTotal = lh * 60 + lm + 15;
    const closeTime  = `${String(Math.floor(closeTotal / 60)).padStart(2, '0')}:${String(closeTotal % 60).padStart(2, '0')}`;

    return `Open ${formatTime(keys[0])} – ${formatTime(closeTime)}`;
}

// ── Month Calendar ────────────────────────────────────────────────────────────

type ClosedRange = { start_date: string; end_date: string; label: string | null };

const DAY_HEADERS = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];

function MonthCalendar({
    availableSlotsByDate,
    closedDateRanges,
    selectedDate,
    todayKey,
    rangeEndKey,
    onDateClick,
}: {
    availableSlotsByDate: Record<string, Record<string, number>>;
    closedDateRanges: ClosedRange[];
    selectedDate: Date | null;
    todayKey: string;
    rangeEndKey: string;
    onDateClick: (dateKey: string, date: Date) => void;
}) {
    const [viewDate, setViewDate] = useState(() => {
        const d = new Date();

        return new Date(d.getFullYear(), d.getMonth(), 1);
    });

    const year  = viewDate.getFullYear();
    const month = viewDate.getMonth();

    // Monday-start: (Sun=0 → pad=6, Mon=1 → pad=0, …)
    const startPad    = (new Date(year, month, 1).getDay() + 6) % 7;
    const daysInMonth = new Date(year, month + 1, 0).getDate();

    const cells: Array<{ date: Date; dateKey: string } | null> = [];

    for (let i = 0; i < startPad; i++) {
        cells.push(null);
    }

    for (let d = 1; d <= daysInMonth; d++) {
        const date = new Date(year, month, d);

        cells.push({ date, dateKey: bookingDateKeyFromDate(date) });
    }

    while (cells.length % 7 !== 0) {
        cells.push(null);
    }

    const prevViewKey = bookingDateKeyFromDate(new Date(year, month - 1, 1));
    const nextViewKey = bookingDateKeyFromDate(new Date(year, month + 1, 1));
    const canGoPrev   = prevViewKey.slice(0, 7) >= todayKey.slice(0, 7);
    const canGoNext   = nextViewKey.slice(0, 7) <= rangeEndKey.slice(0, 7);

    const monthLabel = viewDate.toLocaleDateString('en-US', { month: 'long', year: 'numeric' });
    const selectedKey = selectedDate ? bookingDateKeyFromDate(selectedDate) : null;

    return (
        <div className="rounded-2xl border bg-background p-4 shadow-sm">
            <div className="mb-4 flex items-center gap-2">
                <CalendarDays className="size-4 text-primary" />
                <span className="text-sm font-medium">Select a date</span>
            </div>

            {/* Month navigation */}
            <div className="mb-3 flex items-center justify-between px-1">
                <button
                    type="button"
                    onClick={() => setViewDate(new Date(year, month - 1, 1))}
                    disabled={!canGoPrev}
                    className="flex size-8 items-center justify-center rounded-lg hover:bg-accent disabled:opacity-30 disabled:cursor-not-allowed"
                >
                    <ChevronLeft className="size-4" />
                </button>
                <span className="text-base font-semibold">{monthLabel}</span>
                <button
                    type="button"
                    onClick={() => setViewDate(new Date(year, month + 1, 1))}
                    disabled={!canGoNext}
                    className="flex size-8 items-center justify-center rounded-lg hover:bg-accent disabled:opacity-30 disabled:cursor-not-allowed"
                >
                    <ChevronRight className="size-4" />
                </button>
            </div>

            {/* Day-of-week headers */}
            <div className="mb-1 grid grid-cols-7">
                {DAY_HEADERS.map((h) => (
                    <div key={h} className="py-1 text-center text-xs font-medium text-muted-foreground">
                        {h}
                    </div>
                ))}
            </div>

            {/* Day cells */}
            <div className="grid grid-cols-7 gap-1">
                {cells.map((cell, idx) => {
                    if (!cell) {
                        return <div key={`pad-${idx}`} />;
                    }

                    const { date, dateKey } = cell;
                    // availableSlotsByDate includes ALL dates, even unavailable ones as `{}` — check for actual slots
                    const slots        = availableSlotsByDate[dateKey];
                    const isAvailable  = !!slots && Object.keys(slots).length > 0;
                    const isSelected   = selectedKey === dateKey;
                    const isToday      = dateKey === todayKey;
                    const isPast       = dateKey < todayKey;
                    const isOutOfRange = dateKey > rangeEndKey;
                    const closedRange  = closedDateRanges.find(
                        (r) => dateKey >= r.start_date && dateKey <= r.end_date,
                    );
                    const isClosed     = !!closedRange;
                    const clickable    = isAvailable && !isPast && !isOutOfRange;

                    return (
                        <button
                            key={dateKey}
                            type="button"
                            disabled={!clickable}
                            onClick={() => onDateClick(dateKey, date)}
                            title={isClosed ? (closedRange.label ?? 'Closed') : undefined}
                            className={cn(
                                'relative flex aspect-square flex-col items-center justify-center rounded-xl border-2 text-sm font-bold transition-all select-none',
                                isSelected
                                    ? 'border-primary bg-primary text-primary-foreground shadow-md cursor-pointer'
                                    : clickable
                                    ? 'border-border bg-background text-foreground hover:border-primary/60 hover:bg-primary/5 cursor-pointer'
                                    : isClosed
                                    ? 'border-border/20 bg-destructive/5 text-foreground/30 cursor-not-allowed'
                                    : isToday
                                    ? 'border-primary/30 text-foreground/40 cursor-not-allowed'
                                    : 'border-transparent text-foreground/25 cursor-default',
                            )}
                        >
                            {date.getDate()}
                            {isClosed && !isSelected && (
                                <span className="absolute bottom-1 left-1/2 -translate-x-1/2 text-[7px] font-semibold uppercase tracking-wide text-destructive/60 leading-none">
                                    closed
                                </span>
                            )}
                        </button>
                    );
                })}
            </div>
        </div>
    );
}

// ── Main step component ───────────────────────────────────────────────────────

type Props = {
    scheduledAt?: string | null;
    availableSlotsByDate: Record<string, Record<string, number>>;
    closedDateRanges?: ClosedRange[];
};

export default function Step5DateTime({
    scheduledAt: initialScheduledAt,
    availableSlotsByDate,
    closedDateRanges = [],
}: Props) {
    const timezone = useBookingTimezone();
    const {
        todayKey,
        dateKeyAfterDays,
        formatDateKey,
        dateKeyFromDate,
        localDateFromKey,
    } = useBookingDateTimeFormatters();

    const parsed = parseBookingScheduledAt(initialScheduledAt, timezone);
    const [selectedDate, setSelectedDate] = useState<Date | null>(
        parsed ? localDateFromKey(parsed.dateKey) : null,
    );
    const [selectedTime, setSelectedTime] = useState<string | null>(parsed?.time ?? null);

    // Dialog-local state — never commits to selectedDate/selectedTime until user confirms
    const [overlayDate, setOverlayDate] = useState<string | null>(null);
    const [overlayTime, setOverlayTime] = useState<string | null>(null);

    const scheduledAtValue =
        selectedDate && selectedTime
            ? toBookingScheduledAt(dateKeyFromDate(selectedDate), selectedTime)
            : '';

    const selectedDateLabel = selectedDate
        ? formatDateKey(dateKeyFromDate(selectedDate))
        : null;

    const todayKeyValue = todayKey();
    const rangeEndKey = dateKeyAfterDays(30);

    const timesForDay: Record<string, number> =
        selectedDate ? (availableSlotsByDate[dateKeyFromDate(selectedDate)] ?? {}) : {};

    // Open the dialog for a given date, pre-seeding overlayTime if it's the confirmed date
    const openOverlay = (dateKey: string) => {
        const isSameDate = selectedDate && dateKeyFromDate(selectedDate) === dateKey;

        setOverlayTime(isSameDate ? selectedTime : null);
        setOverlayDate(dateKey);
    };

    const closeOverlay = () => {
        setOverlayDate(null);
        setOverlayTime(null);
    };

    const confirmOverlay = () => {
        if (overlayDate && overlayTime) {
            setSelectedDate(localDateFromKey(overlayDate));
            setSelectedTime(overlayTime);
        }

        closeOverlay();
    };

    const overlayLabel = overlayDate ? formatDateKey(overlayDate) : null;

    const overlayHoursLabel = overlayDate
        ? formatOpenHoursLabel(availableSlotsByDate[overlayDate] ?? {})
        : null;

    const hasConfirmed = !!(selectedDate && selectedTime);

    return (
        <>
            <Head title="Book: date and time" />

            <Form action="/book/datetime" method="post">
                {({ errors, processing }) => (
                    <div className="flex flex-col gap-6">
                        <div>
                            <h2 className="text-xl font-semibold tracking-tight">
                                Select date &amp; time
                            </h2>
                            <p className="mt-1 text-sm text-muted-foreground">
                                Choose a date and available time slot for your service.
                            </p>
                        </div>

                        <input type="hidden" name="scheduled_at" value={scheduledAtValue} />

                        <Tabs defaultValue="calendar">
                            <TabsList variant="line" className="mb-4">
                                <TabsTrigger value="calendar" className="flex items-center gap-1.5">
                                    <Calendar className="size-3.5" />
                                    Calendar
                                </TabsTrigger>
                                <TabsTrigger value="strip" className="flex items-center gap-1.5">
                                    <LayoutList className="size-3.5" />
                                    Strip
                                </TabsTrigger>
                            </TabsList>

                            {/* ── Calendar tab ──────────────────────────────── */}
                            <TabsContent value="calendar" className="flex flex-col gap-4">
                                <MonthCalendar
                                    availableSlotsByDate={availableSlotsByDate}
                                    closedDateRanges={closedDateRanges}
                                    selectedDate={selectedDate}
                                    todayKey={todayKeyValue}
                                    rangeEndKey={rangeEndKey}
                                    onDateClick={(dateKey) => openOverlay(dateKey)}
                                />
                            </TabsContent>

                            {/* ── Strip tab ─────────────────────────────────── */}
                            <TabsContent value="strip" className="flex flex-col gap-4">
                                <div className="rounded-2xl border bg-background p-4 shadow-sm">
                                    <div className="mb-3 flex items-center gap-2">
                                        <CalendarDays className="size-4 text-primary" />
                                        <span className="text-sm font-medium">Select a date</span>
                                    </div>
                                    <DateStrip
                                        selectedDate={selectedDate}
                                        onSelect={(date) => {
                                            setSelectedDate(date);
                                            setSelectedTime(null);
                                        }}
                                        daysAhead={30}
                                        initialOffset={parsed?.offset ?? 0}
                                        availableSlotsByDate={availableSlotsByDate}
                                        closedDateRanges={closedDateRanges}
                                        timezone={timezone}
                                    />
                                </div>

                                {selectedDate && (
                                    <div className="rounded-2xl border bg-background p-4 shadow-sm">
                                        <div className="mb-3">
                                            <span className="text-sm font-medium">Available times</span>
                                            {selectedDateLabel && (
                                                <span className="ml-2 text-sm text-muted-foreground">
                                                    for {selectedDateLabel}
                                                </span>
                                            )}
                                        </div>
                                        <TimeSlotGrid
                                            selectedTime={selectedTime}
                                            onSelect={setSelectedTime}
                                            availableTimes={timesForDay}
                                        />
                                    </div>
                                )}
                            </TabsContent>
                        </Tabs>

                        {/* ── Time slot dialog (shared, portal-rendered) ─── */}
                        <Dialog open={!!overlayDate} onOpenChange={(open) => !open && closeOverlay()}>
                            <DialogContent className="sm:max-w-2xl">
                                <DialogHeader>
                                    <DialogTitle className="text-sm font-medium leading-snug">
                                        Available times
                                        {overlayLabel && (
                                            <span className="ml-1.5 font-normal text-muted-foreground">
                                                for {overlayLabel}
                                            </span>
                                        )}
                                        {overlayHoursLabel && (
                                            <span className="ml-1.5 font-normal text-muted-foreground">
                                                · {overlayHoursLabel}
                                            </span>
                                        )}
                                    </DialogTitle>
                                </DialogHeader>
                                {overlayDate && (
                                    <TimeSlotGrid
                                        selectedTime={overlayTime}
                                        onSelect={setOverlayTime}
                                        availableTimes={availableSlotsByDate[overlayDate] ?? {}}
                                    />
                                )}
                                <DialogFooter>
                                    <Button
                                        type="button"
                                        className="w-full"
                                        disabled={!overlayTime}
                                        onClick={confirmOverlay}
                                    >
                                        {overlayTime
                                            ? hasConfirmed
                                                ? `Update to ${formatTime(overlayTime)}`
                                                : `Confirm ${formatTime(overlayTime)}`
                                            : 'Select a time to confirm'}
                                    </Button>
                                </DialogFooter>
                            </DialogContent>
                        </Dialog>

                        {selectedDate && selectedTime && (
                            <div className="flex items-center gap-4 rounded-2xl border border-primary/25 bg-primary/8 px-5 py-4">
                                <div className="flex size-11 shrink-0 items-center justify-center rounded-full bg-primary/15">
                                    <CheckCircle2 className="size-6 text-primary" />
                                </div>
                                <div className="min-w-0 flex-1">
                                    <p className="text-[11px] font-semibold uppercase tracking-wider text-primary">
                                        Appointment confirmed
                                    </p>
                                    <p className="mt-0.5 font-semibold text-foreground">
                                        {selectedDateLabel}
                                    </p>
                                    <p className="text-sm text-muted-foreground">
                                        {formatTime(selectedTime)}
                                    </p>
                                </div>
                                <button
                                    type="button"
                                    onClick={() => openOverlay(dateKeyFromDate(selectedDate))}
                                    className="shrink-0 rounded-lg px-3 py-1.5 text-xs font-semibold text-primary ring-1 ring-primary/30 hover:bg-primary/10 transition-colors"
                                >
                                    Update
                                </button>
                            </div>
                        )}

                        {errors.scheduled_at && (
                            <p className="text-sm text-destructive">{errors.scheduled_at}</p>
                        )}

                        <Button
                            type="submit"
                            disabled={processing || !selectedDate || !selectedTime}
                            size="lg"
                            className="w-full"
                        >
                            Continue to your info
                        </Button>
                    </div>
                )}
            </Form>
        </>
    );
}
