import { Head, router, useForm, usePage } from '@inertiajs/react';
import { Pencil, Plus, Trash2 } from 'lucide-react';
import type { FormEvent } from 'react';
import { useState } from 'react';
import {
    PaginationControls,
    SortableHeader,
} from '@/components/data-table-controls';
import type {
    PaginatedData,
    TableFilters,
} from '@/components/data-table-controls';
import Heading from '@/components/heading';
import InputError from '@/components/input-error';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import {
    Dialog,
    DialogContent,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { slugify } from '@/lib/utils';
import type { Auth } from '@/types';

type CategoryOption = {
    id: number;
    name: string;
};

type Category = {
    id: number;
    parent_id: number | null;
    name: string;
    slug: string;
    description: string | null;
    is_active: boolean;
    children_count: number;
    created_at: string;
    parent: CategoryOption | null;
};

type PageProps = {
    auth: Auth;
    categories: PaginatedData<Category>;
    categoryOptions: CategoryOption[];
    filters: TableFilters;
};

type CategoryForm = {
    parent_id: number | null;
    name: string;
    slug: string;
    description: string;
    is_active: boolean;
};

const emptyForm: CategoryForm = {
    parent_id: null,
    name: '',
    slug: '',
    description: '',
    is_active: true,
};

export default function CategoriesIndex({
    categories,
    categoryOptions,
    filters,
}: PageProps) {
    const { auth } = usePage<PageProps>().props;
    const [open, setOpen] = useState(false);
    const [editing, setEditing] = useState<Category | null>(null);
    const form = useForm<CategoryForm>(emptyForm);
    const can = (permission: string) => auth.permissions.includes(permission);

    const availableParents = categoryOptions.filter(
        (category) => category.id !== editing?.id,
    );

    const openCreate = () => {
        setEditing(null);
        form.setData(emptyForm);
        form.clearErrors();
        setOpen(true);
    };

    const openEdit = (category: Category) => {
        setEditing(category);
        form.setData({
            parent_id: category.parent_id,
            name: category.name,
            slug: category.slug,
            description: category.description ?? '',
            is_active: category.is_active,
        });
        form.clearErrors();
        setOpen(true);
    };

    const submit = (event: FormEvent) => {
        event.preventDefault();

        if (editing) {
            form.put(`/categories/${editing.id}`, {
                preserveScroll: true,
                onSuccess: () => setOpen(false),
            });

            return;
        }

        form.post('/categories', {
            preserveScroll: true,
            onSuccess: () => setOpen(false),
        });
    };

    const destroy = (category: Category) => {
        if (!window.confirm(`Delete ${category.name}?`)) {
            return;
        }

        router.delete(`/categories/${category.id}`, { preserveScroll: true });
    };

    return (
        <>
            <Head title="Categories" />

            <div className="flex h-full flex-1 flex-col gap-6 overflow-x-auto p-4">
                <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                    <Heading
                        title="Categories"
                        description="Manage product categories and hierarchy."
                    />

                    {can('categories.create') && (
                        <Button onClick={openCreate}>
                            <Plus />
                            New category
                        </Button>
                    )}
                </div>

                <div className="overflow-hidden rounded-lg border">
                    <table className="w-full text-sm">
                        <thead className="bg-muted/50 text-left">
                            <tr>
                                <SortableHeader
                                    basePath="/categories"
                                    column="name"
                                    filters={filters}
                                    className="px-4 py-3"
                                >
                                    Category
                                </SortableHeader>
                                <th className="px-4 py-3 font-medium">
                                    Parent
                                </th>
                                <th className="px-4 py-3 font-medium">
                                    Children
                                </th>
                                <SortableHeader
                                    basePath="/categories"
                                    column="is_active"
                                    filters={filters}
                                    className="px-4 py-3"
                                >
                                    Status
                                </SortableHeader>
                                <SortableHeader
                                    basePath="/categories"
                                    column="created_at"
                                    filters={filters}
                                    className="px-4 py-3"
                                >
                                    Created
                                </SortableHeader>
                                <th className="w-28 px-4 py-3 text-right font-medium">
                                    Actions
                                </th>
                            </tr>
                        </thead>
                        <tbody className="divide-y">
                            {categories.data.map((category) => (
                                <tr key={category.id}>
                                    <td className="px-4 py-3">
                                        <div className="font-medium">
                                            {category.name}
                                        </div>
                                        <div className="text-xs text-muted-foreground">
                                            {category.slug}
                                        </div>
                                    </td>
                                    <td className="px-4 py-3 text-muted-foreground">
                                        {category.parent?.name ?? 'Root'}
                                    </td>
                                    <td className="px-4 py-3 text-muted-foreground">
                                        {category.children_count}
                                    </td>
                                    <td className="px-4 py-3">
                                        <Badge
                                            variant={
                                                category.is_active
                                                    ? 'secondary'
                                                    : 'outline'
                                            }
                                        >
                                            {category.is_active
                                                ? 'Active'
                                                : 'Inactive'}
                                        </Badge>
                                    </td>
                                    <td className="px-4 py-3 text-muted-foreground">
                                        {new Date(
                                            category.created_at,
                                        ).toLocaleDateString()}
                                    </td>
                                    <td className="px-4 py-3">
                                        <div className="flex justify-end gap-2">
                                            {can('categories.update') && (
                                                <Button
                                                    variant="outline"
                                                    size="icon"
                                                    onClick={() =>
                                                        openEdit(category)
                                                    }
                                                >
                                                    <Pencil />
                                                    <span className="sr-only">
                                                        Edit
                                                    </span>
                                                </Button>
                                            )}
                                            {can('categories.delete') && (
                                                <Button
                                                    variant="destructive"
                                                    size="icon"
                                                    onClick={() =>
                                                        destroy(category)
                                                    }
                                                >
                                                    <Trash2 />
                                                    <span className="sr-only">
                                                        Delete
                                                    </span>
                                                </Button>
                                            )}
                                        </div>
                                    </td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                    <PaginationControls
                        basePath="/categories"
                        filters={filters}
                        meta={categories}
                    />
                </div>
            </div>

            <Dialog open={open} onOpenChange={setOpen}>
                <DialogContent>
                    <DialogHeader>
                        <DialogTitle>
                            {editing ? 'Edit category' : 'New category'}
                        </DialogTitle>
                    </DialogHeader>

                    <form onSubmit={submit} className="space-y-4">
                        <div className="grid gap-2">
                            <Label htmlFor="name">Name</Label>
                            <Input
                                id="name"
                                value={form.data.name}
                                onChange={(event) => {
                                    const name = event.target.value;
                                    form.setData('name', name);
                                    form.setData('slug', slugify(name));
                                }}
                            />
                            <InputError message={form.errors.name} />
                        </div>

                        <div className="grid gap-2">
                            <Label htmlFor="slug">Slug</Label>
                            <Input
                                id="slug"
                                value={form.data.slug}
                                readOnly
                                className="bg-muted"
                            />
                            <InputError message={form.errors.slug} />
                        </div>

                        <div className="grid gap-2">
                            <Label>Parent category</Label>
                            <Select
                                value={String(form.data.parent_id ?? 'root')}
                                onValueChange={(value) =>
                                    form.setData(
                                        'parent_id',
                                        value === 'root' ? null : Number(value),
                                    )
                                }
                            >
                                <SelectTrigger className="w-full">
                                    <SelectValue />
                                </SelectTrigger>
                                <SelectContent>
                                    <SelectItem value="root">Root</SelectItem>
                                    {availableParents.map((category) => (
                                        <SelectItem
                                            key={category.id}
                                            value={String(category.id)}
                                        >
                                            {category.name}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                            <InputError message={form.errors.parent_id} />
                        </div>

                        <div className="grid gap-2">
                            <Label htmlFor="description">Description</Label>
                            <Input
                                id="description"
                                value={form.data.description}
                                onChange={(event) =>
                                    form.setData(
                                        'description',
                                        event.target.value,
                                    )
                                }
                            />
                            <InputError message={form.errors.description} />
                        </div>

                        <label className="flex items-center gap-2 text-sm">
                            <Checkbox
                                checked={form.data.is_active}
                                onCheckedChange={(checked) =>
                                    form.setData('is_active', checked === true)
                                }
                            />
                            Active category
                        </label>
                        <InputError message={form.errors.is_active} />

                        <DialogFooter>
                            <Button
                                type="button"
                                variant="outline"
                                onClick={() => setOpen(false)}
                            >
                                Cancel
                            </Button>
                            <Button disabled={form.processing}>Save</Button>
                        </DialogFooter>
                    </form>
                </DialogContent>
            </Dialog>
        </>
    );
}

CategoriesIndex.layout = {
    breadcrumbs: [
        {
            title: 'Categories',
            href: '/categories',
        },
    ],
};
