import { Head, Link, router } from '@inertiajs/react';
import { CalendarOff, Copy, Globe, Plus, Trash2 } from 'lucide-react';
import { useState } from 'react';
import { PageHeader } from '@/components/layout/page-header';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Switch } from '@/components/ui/switch';
import AppLayout from '@/layouts/app-layout';
import { formatBookingTimezone } from '@/lib/booking-timezones';
import adminLocations from '@/routes/admin/locations';
import { edit as editBookingSettings } from '@/routes/settings/booking';
import { CustomScheduleModal } from './custom-schedule-modal';

const DAY_NAMES = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

type SlotInput = { opens_at: string; closes_at: string };
type DayState = { isActive: boolean; slots: SlotInput[] };

type AvailabilitySlot = {
    day_of_week: number;
    opens_at: string;
    closes_at: string;
    is_active: boolean;
};

type ClosedDate = {
    id: number;
    start_date: string;
    end_date: string;
    label: string | null;
};

type Props = {
    location: { id: number; name: string };
    slots: AvailabilitySlot[];
    bookingTimezone: string;
    closedDates: ClosedDate[];
};

function buildTimeOptions(): string[] {
    const opts: string[] = [];
    for (let h = 6; h < 24; h++) {
        for (let m = 0; m < 60; m += 15) {
            opts.push(`${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`);
        }
    }
    return opts;
}

const TIME_OPTIONS = buildTimeOptions();

function formatTime(t: string): string {
    const [h, m] = t.split(':').map(Number);
    const period = h < 12 ? 'AM' : 'PM';
    const hour = h === 0 ? 12 : h > 12 ? h - 12 : h;
    return m === 0 ? `${hour}:00 ${period}` : `${hour}:${String(m).padStart(2, '0')} ${period}`;
}

function initDays(slots: AvailabilitySlot[]): DayState[] {
    return Array.from({ length: 7 }, (_, dayIndex) => {
        const daySlots = slots.filter((s) => s.day_of_week === dayIndex);
        return daySlots.length > 0
            ? {
                  isActive: daySlots.some((s) => s.is_active),
                  slots: daySlots.map((s) => ({ opens_at: s.opens_at, closes_at: s.closes_at })),
              }
            : { isActive: false, slots: [{ opens_at: '09:00', closes_at: '17:00' }] };
    });
}

function TimeSelect({ value, onChange, min }: { value: string; onChange: (v: string) => void; min?: string }) {
    return (
        <select
            value={value}
            onChange={(e) => onChange(e.target.value)}
            className="h-8 rounded-md border border-input bg-background px-2 py-0 text-sm focus:outline-none focus:ring-1 focus:ring-ring"
        >
            {TIME_OPTIONS.map((t) => (
                <option key={t} value={t} disabled={min !== undefined && t <= min}>
                    {formatTime(t)}
                </option>
            ))}
        </select>
    );
}

function CopyPopover({ dayIndex, onCopy }: { dayIndex: number; onCopy: (targets: number[]) => void }) {
    const [open, setOpen] = useState(false);
    const [checked, setChecked] = useState<Set<number>>(new Set());

    const toggle = (d: number) => {
        setChecked((prev) => {
            const next = new Set(prev);
            next.has(d) ? next.delete(d) : next.add(d);
            return next;
        });
    };

    const handleCopy = () => {
        onCopy(Array.from(checked));
        setChecked(new Set());
        setOpen(false);
    };

    return (
        <Popover open={open} onOpenChange={setOpen}>
            <PopoverTrigger asChild>
                <button
                    type="button"
                    className="inline-flex size-7 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
                    title="Copy to other days"
                >
                    <Copy className="size-3.5" />
                </button>
            </PopoverTrigger>
            <PopoverContent className="w-44 p-3" align="start">
                <p className="mb-2 text-xs font-medium text-muted-foreground">Copy schedule to</p>
                <div className="flex flex-col gap-2">
                    {DAY_NAMES.map((name, d) => {
                        if (d === dayIndex) return null;
                        return (
                            <label key={d} className="flex cursor-pointer items-center gap-2 text-sm">
                                <Checkbox checked={checked.has(d)} onCheckedChange={() => toggle(d)} />
                                {name}
                            </label>
                        );
                    })}
                </div>
                <Button size="sm" className="mt-3 w-full" disabled={checked.size === 0} onClick={handleCopy}>
                    Apply
                </Button>
            </PopoverContent>
        </Popover>
    );
}

const MONTHS_SHORT = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

function formatClosedDate(dateKey: string): string {
    const [y, m, d] = dateKey.split('-').map(Number);
    return `${MONTHS_SHORT[m - 1]} ${d}, ${y}`;
}

export default function LocationAvailability({ location, slots, bookingTimezone, closedDates: initialClosedDates }: Props) {
    const [days, setDays] = useState<DayState[]>(() => initDays(slots));
    const [saving, setSaving] = useState(false);
    const [showModal, setShowModal] = useState(false);

    const updateDay = (i: number, patch: Partial<DayState>) =>
        setDays((prev) => prev.map((d, idx) => (idx === i ? { ...d, ...patch } : d)));

    const updateSlot = (dayIdx: number, slotIdx: number, patch: Partial<SlotInput>) =>
        setDays((prev) =>
            prev.map((d, i) =>
                i !== dayIdx
                    ? d
                    : { ...d, slots: d.slots.map((s, si) => (si === slotIdx ? { ...s, ...patch } : s)) },
            ),
        );

    const addSlot = (dayIdx: number) =>
        setDays((prev) =>
            prev.map((d, i) => {
                if (i !== dayIdx) return d;
                const last = d.slots[d.slots.length - 1];
                return { ...d, slots: [...d.slots, { opens_at: last?.closes_at ?? '09:00', closes_at: '19:00' }] };
            }),
        );

    const removeSlot = (dayIdx: number, slotIdx: number) =>
        setDays((prev) =>
            prev.map((d, i) =>
                i !== dayIdx ? d : { ...d, slots: d.slots.filter((_, si) => si !== slotIdx) },
            ),
        );

    const copyToOtherDays = (sourceIdx: number, targets: number[]) => {
        const source = days[sourceIdx];
        setDays((prev) =>
            prev.map((d, i) =>
                targets.includes(i)
                    ? { ...d, isActive: source.isActive, slots: source.slots.map((s) => ({ ...s })) }
                    : d,
            ),
        );
    };

    const handleSave = () => {
        const slotsPayload: AvailabilitySlot[] = [];
        days.forEach((day, dayIndex) => {
            day.slots.forEach((slot) => {
                slotsPayload.push({ day_of_week: dayIndex, opens_at: slot.opens_at, closes_at: slot.closes_at, is_active: day.isActive });
            });
        });
        setSaving(true);
        router.post(adminLocations.availability.sync.url(location.id), { slots: slotsPayload }, { onFinish: () => setSaving(false) });
    };

    return (
        <>
            <Head title={`Availability — ${location.name}`} />
            <div className="mx-auto max-w-2xl space-y-6 p-6">
                <PageHeader
                    title="Availability"
                    description="Set your available booking hours."
                    actions={
                        <Link href={adminLocations.index.url()}>
                            <Button variant="outline" size="sm">Back to Locations</Button>
                        </Link>
                    }
                />

                {/* Location label */}
                <p className="text-sm font-medium text-muted-foreground">{location.name}</p>

                {/* Holidays & Days Off card */}
                <div className="rounded-xl border bg-card shadow-sm">
                    <div className="flex items-center justify-between px-5 py-4">
                        <div className="flex items-center gap-2">
                            <CalendarOff className="size-4 text-muted-foreground" />
                            <span className="font-medium">Holidays &amp; Days Off</span>
                        </div>
                        <Button size="sm" variant="outline" onClick={() => setShowModal(true)}>
                            <Plus className="size-3.5" />
                            Add
                        </Button>
                    </div>

                    {initialClosedDates.length > 0 && (
                        <div className="divide-y border-t">
                            {initialClosedDates.map((cd) => (
                                <div key={cd.id} className="flex items-center gap-3 px-5 py-3">
                                    <div className="flex-1 min-w-0">
                                        <p className="text-sm font-medium">
                                            {cd.start_date === cd.end_date
                                                ? formatClosedDate(cd.start_date)
                                                : `${formatClosedDate(cd.start_date)} – ${formatClosedDate(cd.end_date)}`}
                                        </p>
                                        {cd.label && (
                                            <p className="text-xs text-muted-foreground truncate">{cd.label}</p>
                                        )}
                                    </div>
                                    <button
                                        type="button"
                                        onClick={() =>
                                            router.delete(
                                                adminLocations.closedDates.destroy.url({
                                                    location: location.id,
                                                    closedDate: cd.id,
                                                }),
                                            )
                                        }
                                        className="inline-flex size-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-destructive"
                                        title="Remove day off"
                                    >
                                        <Trash2 className="size-3.5" />
                                    </button>
                                </div>
                            ))}
                        </div>
                    )}

                    {initialClosedDates.length === 0 && (
                        <p className="border-t px-5 py-4 text-sm text-muted-foreground">
                            No holidays or days off set. Customers can book on any available day.
                        </p>
                    )}
                </div>

                {/* Weekly schedule card */}
                <div className="rounded-xl border bg-card shadow-sm">
                    {/* Timezone row */}
                    <div className="flex items-center gap-3 border-b px-5 py-3">
                        <Globe className="size-4 shrink-0 text-muted-foreground" />
                        <span className="text-sm text-muted-foreground">Timezone</span>
                        <div className="ml-auto flex items-center gap-2 text-sm">
                            <span className="font-medium">{formatBookingTimezone(bookingTimezone)}</span>
                            <Link
                                href={editBookingSettings.url()}
                                className="text-xs text-muted-foreground underline-offset-4 hover:text-foreground hover:underline"
                            >
                                Change in Booking Settings
                            </Link>
                        </div>
                    </div>

                    {/* Day rows */}
                    <div className="divide-y">
                        {DAY_NAMES.map((dayName, dayIndex) => {
                            const day = days[dayIndex];
                            return (
                                <div key={dayIndex} className="flex items-start gap-4 px-5 py-4">
                                    {/* Toggle + day name */}
                                    <div className="flex w-32 shrink-0 items-center gap-2.5 pt-0.5">
                                        <Switch
                                            checked={day.isActive}
                                            onCheckedChange={(v) => updateDay(dayIndex, { isActive: v })}
                                            id={`day-${dayIndex}`}
                                        />
                                        <Label
                                            htmlFor={`day-${dayIndex}`}
                                            className={`cursor-pointer text-sm font-medium select-none ${day.isActive ? 'text-foreground' : 'text-muted-foreground'}`}
                                        >
                                            {dayName}
                                        </Label>
                                    </div>

                                    {/* Slots or unavailable text */}
                                    {day.isActive ? (
                                        <div className="flex flex-1 flex-col gap-2">
                                            {day.slots.map((slot, slotIndex) => (
                                                <div key={slotIndex} className="flex items-center gap-2">
                                                    <TimeSelect
                                                        value={slot.opens_at}
                                                        onChange={(v) => updateSlot(dayIndex, slotIndex, { opens_at: v })}
                                                    />
                                                    <span className="shrink-0 text-sm text-muted-foreground">-</span>
                                                    <TimeSelect
                                                        value={slot.closes_at}
                                                        min={slot.opens_at}
                                                        onChange={(v) => updateSlot(dayIndex, slotIndex, { closes_at: v })}
                                                    />
                                                    <button
                                                        type="button"
                                                        onClick={() => removeSlot(dayIndex, slotIndex)}
                                                        className="ml-1 inline-flex size-7 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-destructive"
                                                    >
                                                        <Trash2 className="size-3.5" />
                                                    </button>
                                                </div>
                                            ))}
                                            {/* Add + Copy row */}
                                            <div className="flex items-center gap-1">
                                                <button
                                                    type="button"
                                                    onClick={() => addSlot(dayIndex)}
                                                    className="inline-flex items-center gap-1 rounded-md px-1.5 py-1 text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
                                                >
                                                    <Plus className="size-3" />
                                                    Add time
                                                </button>
                                                <CopyPopover dayIndex={dayIndex} onCopy={(t) => copyToOtherDays(dayIndex, t)} />
                                            </div>
                                        </div>
                                    ) : (
                                        <p className="pt-0.5 text-sm text-muted-foreground">Unavailable</p>
                                    )}
                                </div>
                            );
                        })}
                    </div>

                    {/* Footer */}
                    <div className="flex items-center justify-between border-t px-5 py-3">
                        <div className="flex items-center gap-1.5 text-xs text-muted-foreground">
                            <Globe className="size-3.5" />
                            <span>{formatBookingTimezone(bookingTimezone)}</span>
                        </div>
                        <Button onClick={handleSave} disabled={saving} size="sm">
                            {saving ? 'Saving…' : 'Save availability'}
                        </Button>
                    </div>
                </div>
            </div>
            <CustomScheduleModal
                open={showModal}
                onClose={() => setShowModal(false)}
                locationId={location.id}
            />
        </>
    );
}

LocationAvailability.layout = (page: React.ReactNode) => <AppLayout>{page}</AppLayout>;
