import { Link, useForm } from '@inertiajs/react';
import { Plus, Trash2 } from 'lucide-react';
import type { FormEvent } from 'react';
import InputError from '@/components/input-error';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { slugify } from '@/lib/utils';

export type ProductOption = {
    id: number;
    name: string;
};

export type ProductVariation = {
    id: number;
    color: string | null;
    size: string | null;
    sku: string | null;
    price: string | null;
    stock: number;
};

export type Product = {
    id: number;
    store_id: number;
    category_id: number;
    brand_id: number;
    name: string;
    slug: string;
    sku: string | null;
    price: string;
    stock: number;
    feature_image_url: string | null;
    description: string | null;
    is_active: boolean;
    variations: ProductVariation[];
};

type VariationForm = {
    color: string;
    size: string;
    sku: string;
    price: string;
    stock: string;
};

type ProductFormData = {
    store_id: number | null;
    category_id: number | null;
    brand_id: number | null;
    name: string;
    slug: string;
    sku: string;
    price: string;
    stock: string;
    feature_image: File | null;
    description: string;
    is_active: boolean;
    variations: VariationForm[];
};

type ProductFormProps = {
    brands: ProductOption[];
    categories: ProductOption[];
    product?: Product;
    stores: ProductOption[];
};

const emptyVariation: VariationForm = {
    color: '',
    size: '',
    sku: '',
    price: '',
    stock: '0',
};

const productToForm = (product?: Product): ProductFormData => ({
    store_id: product?.store_id ?? null,
    category_id: product?.category_id ?? null,
    brand_id: product?.brand_id ?? null,
    name: product?.name ?? '',
    slug: product?.slug ?? '',
    sku: product?.sku ?? '',
    price: product?.price ?? '0',
    stock: product ? String(product.stock) : '0',
    feature_image: null,
    description: product?.description ?? '',
    is_active: product?.is_active ?? true,
    variations:
        product?.variations.map((variation) => ({
            color: variation.color ?? '',
            size: variation.size ?? '',
            sku: variation.sku ?? '',
            price: variation.price ?? '',
            stock: String(variation.stock),
        })) ?? [],
});

export default function ProductForm({
    brands,
    categories,
    product,
    stores,
}: ProductFormProps) {
    const form = useForm<ProductFormData>(productToForm(product));
    const fieldErrors = form.errors as Record<string, string | undefined>;

    const addVariation = () => {
        form.setData('variations', [...form.data.variations, emptyVariation]);
    };

    const updateVariation = (
        index: number,
        key: keyof VariationForm,
        value: string,
    ) => {
        form.setData(
            'variations',
            form.data.variations.map((variation, currentIndex) =>
                currentIndex === index
                    ? { ...variation, [key]: value }
                    : variation,
            ),
        );
    };

    const removeVariation = (index: number) => {
        form.setData(
            'variations',
            form.data.variations.filter(
                (_, currentIndex) => currentIndex !== index,
            ),
        );
    };

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

        if (product) {
            form.post(`/products/${product.id}`, {
                forceFormData: true,
                preserveScroll: true,
            });

            return;
        }

        form.post('/products', {
            forceFormData: true,
            preserveScroll: true,
        });
    };

    return (
        <form onSubmit={submit} className="space-y-6 p-4">
            <div className="grid gap-4 sm:grid-cols-3">
                <div className="grid gap-2">
                    <Label>Store</Label>
                    <Select
                        value={String(form.data.store_id ?? '')}
                        onValueChange={(value) =>
                            form.setData('store_id', Number(value))
                        }
                    >
                        <SelectTrigger className="w-full">
                            <SelectValue placeholder="Select store" />
                        </SelectTrigger>
                        <SelectContent>
                            {stores.map((store) => (
                                <SelectItem
                                    key={store.id}
                                    value={String(store.id)}
                                >
                                    {store.name}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>
                    <InputError message={form.errors.store_id} />
                </div>

                <div className="grid gap-2">
                    <Label>Category</Label>
                    <Select
                        value={String(form.data.category_id ?? '')}
                        onValueChange={(value) =>
                            form.setData('category_id', Number(value))
                        }
                    >
                        <SelectTrigger className="w-full">
                            <SelectValue placeholder="Select category" />
                        </SelectTrigger>
                        <SelectContent>
                            {categories.map((category) => (
                                <SelectItem
                                    key={category.id}
                                    value={String(category.id)}
                                >
                                    {category.name}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>
                    <InputError message={form.errors.category_id} />
                </div>

                <div className="grid gap-2">
                    <Label>Brand</Label>
                    <Select
                        value={String(form.data.brand_id ?? '')}
                        onValueChange={(value) =>
                            form.setData('brand_id', Number(value))
                        }
                    >
                        <SelectTrigger className="w-full">
                            <SelectValue placeholder="Select brand" />
                        </SelectTrigger>
                        <SelectContent>
                            {brands.map((brand) => (
                                <SelectItem
                                    key={brand.id}
                                    value={String(brand.id)}
                                >
                                    {brand.name}
                                </SelectItem>
                            ))}
                        </SelectContent>
                    </Select>
                    <InputError message={form.errors.brand_id} />
                </div>
            </div>

            <div className="grid gap-4 sm:grid-cols-2">
                <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>

            <div className="grid gap-4 sm:grid-cols-3">
                <div className="grid gap-2">
                    <Label htmlFor="sku">SKU</Label>
                    <Input
                        id="sku"
                        value={form.data.sku}
                        onChange={(event) =>
                            form.setData('sku', event.target.value)
                        }
                    />
                    <InputError message={form.errors.sku} />
                </div>

                <div className="grid gap-2">
                    <Label htmlFor="price">Price</Label>
                    <Input
                        id="price"
                        type="number"
                        step="0.01"
                        min="0"
                        value={form.data.price}
                        onChange={(event) =>
                            form.setData('price', event.target.value)
                        }
                    />
                    <InputError message={form.errors.price} />
                </div>

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

            <div className="grid gap-2">
                <Label htmlFor="feature_image">Feature image</Label>
                <Input
                    id="feature_image"
                    type="file"
                    accept="image/*"
                    onChange={(event) =>
                        form.setData(
                            'feature_image',
                            event.target.files?.[0] ?? null,
                        )
                    }
                />
                {product?.feature_image_url && (
                    <div className="flex items-center gap-3 text-sm text-muted-foreground">
                        <img
                            src={product.feature_image_url}
                            alt={product.name}
                            className="size-10 rounded-md border object-cover"
                        />
                        Current image will be kept unless you upload a new one.
                    </div>
                )}
                <InputError message={form.errors.feature_image} />
            </div>

            <div className="grid gap-2">
                <Label htmlFor="description">Description</Label>
                <Textarea
                    id="description"
                    value={form.data.description}
                    onChange={(event) =>
                        form.setData('description', event.target.value)
                    }
                    rows={5}
                />
                <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 product
            </label>
            <InputError message={form.errors.is_active} />

            <div className="grid gap-3">
                <div className="flex items-center justify-between gap-3">
                    <Label>Variations</Label>
                    <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        onClick={addVariation}
                    >
                        <Plus />
                        Add variation
                    </Button>
                </div>

                <div className="overflow-hidden rounded-md border">
                    <table className="w-full text-sm">
                        <thead className="bg-muted/50 text-left">
                            <tr>
                                <th className="px-3 py-2 font-medium">Color</th>
                                <th className="px-3 py-2 font-medium">Size</th>
                                <th className="px-3 py-2 font-medium">SKU</th>
                                <th className="px-3 py-2 font-medium">Price</th>
                                <th className="px-3 py-2 font-medium">Stock</th>
                                <th className="w-12 px-3 py-2" />
                            </tr>
                        </thead>
                        <tbody className="divide-y">
                            {form.data.variations.length ? (
                                form.data.variations.map((variation, index) => (
                                    <tr key={index}>
                                        <td className="px-3 py-2">
                                            <Input
                                                value={variation.color}
                                                onChange={(event) =>
                                                    updateVariation(
                                                        index,
                                                        'color',
                                                        event.target.value,
                                                    )
                                                }
                                            />
                                            <InputError
                                                message={
                                                    fieldErrors[
                                                        `variations.${index}.color`
                                                    ]
                                                }
                                            />
                                        </td>
                                        <td className="px-3 py-2">
                                            <Input
                                                value={variation.size}
                                                onChange={(event) =>
                                                    updateVariation(
                                                        index,
                                                        'size',
                                                        event.target.value,
                                                    )
                                                }
                                            />
                                            <InputError
                                                message={
                                                    fieldErrors[
                                                        `variations.${index}.size`
                                                    ]
                                                }
                                            />
                                        </td>
                                        <td className="px-3 py-2">
                                            <Input
                                                value={variation.sku}
                                                onChange={(event) =>
                                                    updateVariation(
                                                        index,
                                                        'sku',
                                                        event.target.value,
                                                    )
                                                }
                                            />
                                            <InputError
                                                message={
                                                    fieldErrors[
                                                        `variations.${index}.sku`
                                                    ]
                                                }
                                            />
                                        </td>
                                        <td className="px-3 py-2">
                                            <Input
                                                type="number"
                                                step="0.01"
                                                min="0"
                                                value={variation.price}
                                                onChange={(event) =>
                                                    updateVariation(
                                                        index,
                                                        'price',
                                                        event.target.value,
                                                    )
                                                }
                                            />
                                            <InputError
                                                message={
                                                    fieldErrors[
                                                        `variations.${index}.price`
                                                    ]
                                                }
                                            />
                                        </td>
                                        <td className="px-3 py-2">
                                            <Input
                                                type="number"
                                                min="0"
                                                value={variation.stock}
                                                onChange={(event) =>
                                                    updateVariation(
                                                        index,
                                                        'stock',
                                                        event.target.value,
                                                    )
                                                }
                                            />
                                            <InputError
                                                message={
                                                    fieldErrors[
                                                        `variations.${index}.stock`
                                                    ]
                                                }
                                            />
                                        </td>
                                        <td className="px-3 py-2 text-right">
                                            <Button
                                                type="button"
                                                variant="ghost"
                                                size="icon"
                                                onClick={() =>
                                                    removeVariation(index)
                                                }
                                            >
                                                <Trash2 />
                                                <span className="sr-only">
                                                    Remove variation
                                                </span>
                                            </Button>
                                        </td>
                                    </tr>
                                ))
                            ) : (
                                <tr>
                                    <td
                                        colSpan={6}
                                        className="px-3 py-6 text-center text-muted-foreground"
                                    >
                                        No variations added.
                                    </td>
                                </tr>
                            )}
                        </tbody>
                    </table>
                </div>
                <InputError message={form.errors.variations} />
            </div>

            <div className="flex items-center justify-end gap-2">
                <Button variant="outline" asChild>
                    <Link href="/products">Cancel</Link>
                </Button>
                <Button disabled={form.processing}>Save</Button>
            </div>
        </form>
    );
}
