import { Form, Head, Link, router, useForm } from '@inertiajs/react';
import type { ColumnDef } from '@tanstack/react-table';
import { Plus, Settings, Users } from 'lucide-react';
import type { FormEvent } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { DataTable } from '@/components/data-table';
import { FormField } from '@/components/form-field';
import { EmptyState } from '@/components/layout/empty-state';
import { FormDrawer } from '@/components/layout/form-drawer';
import { PageHeader } from '@/components/layout/page-header';
import { SectionCard } from '@/components/layout/section-card';
import { ResourceActionsMenu } from '@/components/resource-actions-menu';
import { ResponsiveDialog } from '@/components/responsive-dialog';
import { Button } from '@/components/ui/button';
import { DialogFooter } from '@/components/ui/dialog';
import { SheetFooter } from '@/components/ui/sheet';
import { InputGroup, InputGroupAddon, InputGroupText, InputGroupTextarea } from '@/components/ui/input-group';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { NativeSelect } from '@/components/ui/native-select';
import { Switch } from '@/components/ui/switch';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import AppLayout from '@/layouts/app-layout';
import adminBookings from '@/routes/admin/bookings';
import adminLocationTypes from '@/routes/admin/location-types';
import adminLocations from '@/routes/admin/locations';

type LocationType = {
    id: number;
    slug: string;
    label: string;
    description: string | null;
    is_active: boolean;
};

type LocationRow = {
    id: number;
    name: string;
    type: string;
    city: string | null;
    state: string | null;
    zip: string | null;
    is_active: boolean;
    display_order: number;
};

type Props = {
    locations: LocationRow[];
    locationTypes: LocationType[];
};

function LocationTypesSection({ locationTypes }: { locationTypes: LocationType[] }) {
    const [addDialogOpen, setAddDialogOpen] = useState(false);
    const [editingType, setEditingType] = useState<LocationType | null>(null);

    const addForm = useForm({ label: '', description: '' });
    const editForm = useForm({ label: '', description: '', is_active: true });

    const openAdd = () => {
        addForm.reset();
        addForm.clearErrors();
        setAddDialogOpen(true);
    };

    const closeAdd = () => {
        setAddDialogOpen(false);
        addForm.reset();
        addForm.clearErrors();
    };

    const openEdit = (locationType: LocationType) => {
        setEditingType(locationType);
        editForm.setData({ label: locationType.label, description: locationType.description ?? '', is_active: locationType.is_active });
        editForm.clearErrors();
    };

    const closeEdit = () => {
        setEditingType(null);
        editForm.reset();
        editForm.clearErrors();
    };

    const submitAdd = (event: FormEvent<HTMLFormElement>) => {
        event.preventDefault();
        addForm.post(adminLocationTypes.store.url(), {
            onSuccess: () => closeAdd(),
        });
    };

    const submitEdit = (event: FormEvent<HTMLFormElement>) => {
        event.preventDefault();

        if (!editingType) {
            return;
        }

        editForm.patch(adminLocationTypes.update.url({ locationType: editingType.id }), {
            onSuccess: () => closeEdit(),
        });
    };

    const toggleActive = (locationType: LocationType) => {
        router.patch(
            adminLocationTypes.update.url({ locationType: locationType.id }),
            { label: locationType.label, is_active: !locationType.is_active },
            { preserveScroll: true },
        );
    };

    const deleteType = (locationType: LocationType) => {
        router.delete(adminLocationTypes.destroy.url({ locationType: locationType.id }), {
            preserveScroll: true,
        });
    };

    return (
        <>
            <SectionCard
                title="Location types"
                actions={
                    <Button size="sm" onClick={openAdd}>
                        <Plus className="size-4" />
                        Add type
                    </Button>
                }
            >
                {locationTypes.length === 0 ? (
                    <EmptyState title="No types yet" description="Add a type to get started." />
                ) : (
                    <div className="divide-y rounded-md border">
                        {locationTypes.map((locationType) => (
                            <div key={locationType.id} className="flex items-center gap-3 px-4 py-3">
                                <div className="flex-1 min-w-0">
                                    <p className="truncate font-medium text-sm">{locationType.label}</p>
                                    <p className="text-xs text-muted-foreground">{locationType.slug}</p>
                                    {locationType.description && (
                                        <p className="mt-0.5 truncate text-xs text-muted-foreground/70">{locationType.description}</p>
                                    )}
                                </div>
                                <div className="flex items-center gap-1">
                                    <Switch
                                        checked={locationType.is_active}
                                        onCheckedChange={() => toggleActive(locationType)}
                                        aria-label={locationType.is_active ? 'Deactivate' : 'Activate'}
                                    />
                                    <ResourceActionsMenu
                                        onEdit={() => openEdit(locationType)}
                                        onDelete={() => deleteType(locationType)}
                                        deleteTitle="Delete type?"
                                        deleteDescription={`Locations currently set to "${locationType.label}" must be reassigned first.`}
                                    />
                                </div>
                            </div>
                        ))}
                    </div>
                )}
            </SectionCard>

            <ResponsiveDialog
                open={addDialogOpen}
                onOpenChange={(open) => { if (!open) { closeAdd(); } }}
                title="Add location type"
            >
                <form onSubmit={submitAdd} className="grid gap-4">
                    <FormField label="Label" htmlFor="new-type-label" error={addForm.errors.label}>
                        <Input
                            id="new-type-label"
                            placeholder="e.g. Truck wash"
                            value={addForm.data.label}
                            onChange={(e) => addForm.setData('label', e.target.value)}
                            autoFocus
                        />
                    </FormField>
                    <FormField label="Description" htmlFor="new-type-description" error={addForm.errors.description}>
                        <InputGroup>
                            <InputGroupTextarea
                                id="new-type-description"
                                placeholder="Short description shown to customers"
                                maxLength={300}
                                value={addForm.data.description}
                                onChange={(e) => addForm.setData('description', e.target.value)}
                            />
                            <InputGroupAddon align="block-end">
                                <InputGroupText className="text-xs text-muted-foreground">
                                    {300 - addForm.data.description.length} characters left
                                </InputGroupText>
                            </InputGroupAddon>
                        </InputGroup>
                    </FormField>
                    <DialogFooter>
                        <Button type="button" variant="outline" onClick={closeAdd}>Cancel</Button>
                        <Button type="submit" disabled={addForm.processing}>Add type</Button>
                    </DialogFooter>
                </form>
            </ResponsiveDialog>

            <FormDrawer
                open={editingType !== null}
                onOpenChange={(open) => {
                    if (!open) {
                        closeEdit();
                    }
                }}
                title="Edit type"
                direction="right"
            >
                <form onSubmit={submitEdit} className="grid gap-3">
                    <FormField label="Label" htmlFor="edit-type-label" error={editForm.errors.label}>
                        <Input
                            id="edit-type-label"
                            value={editForm.data.label}
                            onChange={(e) => editForm.setData('label', e.target.value)}
                        />
                    </FormField>
                    <FormField label="Description" htmlFor="edit-type-description" error={editForm.errors.description}>
                        <InputGroup>
                            <InputGroupTextarea
                                id="edit-type-description"
                                placeholder="Short description shown to customers"
                                maxLength={300}
                                value={editForm.data.description}
                                onChange={(e) => editForm.setData('description', e.target.value)}
                            />
                            <InputGroupAddon align="block-end">
                                <InputGroupText className="text-xs text-muted-foreground">
                                    {300 - editForm.data.description.length} characters left
                                </InputGroupText>
                            </InputGroupAddon>
                        </InputGroup>
                    </FormField>
                    {editingType && (
                        <p className="text-xs text-muted-foreground">
                            Slug: <span className="font-mono">{editingType.slug}</span> (cannot be changed)
                        </p>
                    )}
                    <div className="flex items-center gap-2">
                        <Switch
                            id="edit-type-active"
                            checked={editForm.data.is_active}
                            onCheckedChange={(checked) => editForm.setData('is_active', checked)}
                        />
                        <Label htmlFor="edit-type-active">Active</Label>
                    </div>
                    <SheetFooter className="px-0 pb-0 sm:flex-row">
                        <Button type="button" variant="outline" onClick={closeEdit}>Cancel</Button>
                        <Button type="submit" disabled={editForm.processing}>Save changes</Button>
                    </SheetFooter>
                </form>
            </FormDrawer>
        </>
    );
}

export default function AdminLocationsIndex({ locations, locationTypes }: Props) {
    const [editingLocation, setEditingLocation] = useState<LocationRow | null>(null);
    const editForm = useForm({
        name: '',
        type: '',
        city: '',
        zip: '',
        is_active: true,
    });

    const activeTypes = locationTypes.filter((t) => t.is_active);

    const editTypeOptions = useMemo(() => {
        if (!editingLocation) return activeTypes;
        const currentType = locationTypes.find((t) => t.slug === editingLocation.type);
        if (!currentType || currentType.is_active) return activeTypes;
        return [currentType, ...activeTypes];
    }, [activeTypes, editingLocation, locationTypes]);

    const openEdit = useCallback((location: LocationRow) => {
        setEditingLocation(location);
        editForm.setData({
            name: location.name,
            type: location.type,
            city: location.city ?? '',
            zip: location.zip ?? '',
            is_active: location.is_active,
        });
        editForm.clearErrors();
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    const closeEdit = () => {
        setEditingLocation(null);
        editForm.reset();
        editForm.clearErrors();
    };

    const submitEdit = (event: FormEvent<HTMLFormElement>) => {
        event.preventDefault();

        if (!editingLocation) {
            return;
        }

        editForm.patch(
            adminLocations.update.url({ location: editingLocation.id }),
            { onSuccess: () => closeEdit() },
        );
    };

    const deleteLocation = useCallback((locationId: number) => {
        router.delete(adminLocations.destroy.url({ location: locationId }));
    }, []);

    const handleReorder = useCallback((ids: (number | string)[]) => {
        router.post(adminLocations.reorder.url(), { ids }, { preserveScroll: true });
    }, []);

    const typeLabel = useCallback(
        (slug: string) => locationTypes.find((t) => t.slug === slug)?.label ?? slug,
        [locationTypes],
    );

    const columns = useMemo<ColumnDef<LocationRow>[]>(
        () => [
            {
                accessorKey: 'name',
                header: 'Name',
                meta: { label: 'Name' },
            },
            {
                accessorKey: 'type',
                header: 'Type',
                meta: { label: 'Type' },
                cell: ({ row }) => typeLabel(row.getValue('type')),
            },
            {
                accessorKey: 'city',
                header: 'City',
                meta: { label: 'City' },
                cell: ({ row }) => row.getValue('city') ?? '-',
            },
            {
                accessorKey: 'zip',
                header: 'Zip',
                meta: { label: 'Zip' },
                cell: ({ row }) => row.getValue('zip') ?? '-',
            },
            {
                accessorKey: 'is_active',
                header: 'Active',
                meta: { label: 'Active' },
                cell: ({ row }) => (row.getValue('is_active') ? 'Yes' : 'No'),
            },
            {
                id: 'actions',
                enableHiding: false,
                header: () => <span className="sr-only">Actions</span>,
                cell: ({ row }) => (
                    <div className="flex items-center gap-1">
                        <Tooltip>
                            <TooltipTrigger asChild>
                                <Button variant="ghost" size="icon" className="size-8" asChild>
                                    <Link href={adminLocations.availability.show.url(row.original.id)}>
                                        <Settings className="size-4" />
                                    </Link>
                                </Button>
                            </TooltipTrigger>
                            <TooltipContent>Manage availability</TooltipContent>
                        </Tooltip>
                        <Tooltip>
                            <TooltipTrigger asChild>
                                <Button variant="ghost" size="icon" className="size-8" asChild>
                                    <Link href={adminLocations.technicians.show.url(row.original.id)}>
                                        <Users className="size-4" />
                                    </Link>
                                </Button>
                            </TooltipTrigger>
                            <TooltipContent>Manage technicians</TooltipContent>
                        </Tooltip>
                        <ResourceActionsMenu
                            onEdit={() => openEdit(row.original)}
                            onDelete={() => deleteLocation(row.original.id)}
                            deleteTitle="Delete location?"
                            deleteDescription="This removes the location from booking setup. Existing bookings keep their records."
                        />
                    </div>
                ),
            },
        ],
        [deleteLocation, openEdit, typeLabel],
    );

    return (
        <>
            <Head title="Admin locations" />
            <div className="flex h-full flex-1 flex-col gap-6">
                <PageHeader
                    title="Locations"
                    actions={
                        <Button variant="outline" size="sm" asChild>
                            <Link href={adminBookings.index.url()}>Back to bookings</Link>
                        </Button>
                    }
                />

                <SectionCard title="Add location">
                    <Form
                        action={adminLocations.store.url()}
                        method="post"
                        className="grid gap-3 md:grid-cols-4"
                    >
                        <FormField label="Name" htmlFor="name">
                            <Input id="name" name="name" />
                        </FormField>
                        <FormField label="Type" htmlFor="type">
                            <NativeSelect id="type" name="type">
                                {activeTypes.map((t) => (
                                    <option key={t.id} value={t.slug}>{t.label}</option>
                                ))}
                            </NativeSelect>
                        </FormField>
                        <FormField label="City" htmlFor="city">
                            <Input id="city" name="city" />
                        </FormField>
                        <FormField label="Zip" htmlFor="zip">
                            <Input id="zip" name="zip" />
                        </FormField>
                        <input type="hidden" name="is_active" value="1" />
                        <div className="md:col-span-4">
                            <Button type="submit">Create location</Button>
                        </div>
                    </Form>
                </SectionCard>

                <LocationTypesSection locationTypes={locationTypes} />

                <SectionCard title="All locations">
                    {locations.length === 0 ? (
                        <EmptyState
                            title="No locations yet"
                            description="Create a location to start taking bookings."
                        />
                    ) : (
                        <DataTable
                            columns={columns}
                            data={locations}
                            searchPlaceholder="Search locations..."
                            onReorder={handleReorder}
                        />
                    )}
                </SectionCard>
            </div>

            <FormDrawer
                open={editingLocation !== null}
                onOpenChange={(open) => {
                    if (!open) {
                        closeEdit();
                    }
                }}
                title="Edit location"
                direction="right"
            >
                <form onSubmit={submitEdit} className="grid gap-3">
                    <FormField label="Name" htmlFor="edit-name">
                        <Input
                            id="edit-name"
                            value={editForm.data.name}
                            onChange={(e) => editForm.setData('name', e.target.value)}
                        />
                    </FormField>
                    <FormField label="Type" htmlFor="edit-type">
                        <NativeSelect
                            id="edit-type"
                            value={editForm.data.type}
                            onChange={(e) => editForm.setData('type', e.target.value)}
                        >
                            {editTypeOptions.map((t) => (
                                <option key={t.id} value={t.slug}>{t.label}{!t.is_active ? ' (inactive)' : ''}</option>
                            ))}
                        </NativeSelect>
                    </FormField>
                    <FormField label="City" htmlFor="edit-city">
                        <Input
                            id="edit-city"
                            value={editForm.data.city}
                            onChange={(e) => editForm.setData('city', e.target.value)}
                        />
                    </FormField>
                    <FormField label="Zip" htmlFor="edit-zip">
                        <Input
                            id="edit-zip"
                            value={editForm.data.zip}
                            onChange={(e) => editForm.setData('zip', e.target.value)}
                        />
                    </FormField>
                    <div className="flex items-center gap-2">
                        <Switch
                            id="edit-is-active"
                            checked={editForm.data.is_active}
                            onCheckedChange={(checked) => editForm.setData('is_active', checked)}
                        />
                        <Label htmlFor="edit-is-active">Active</Label>
                    </div>
                    <SheetFooter className="px-0 pb-0 sm:flex-row">
                        <Button type="button" variant="outline" onClick={closeEdit}>Cancel</Button>
                        <Button type="submit" disabled={editForm.processing}>Save changes</Button>
                    </SheetFooter>
                </form>
            </FormDrawer>
        </>
    );
}

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