import { useForm } from '@inertiajs/react';
import { Package, PackagePlus, Plus, Trash2 } from 'lucide-react';
import { useMemo, type FormEvent } from 'react';
import WarehouseController from '@/actions/App/Http/Controllers/Admin/WarehouseController';
import InputError from '@/components/input-error';
import { Button } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
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 { formatDate } from '@/lib/utils';

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

type LineForm = {
    uid: string;
    product_id: string;
    quantity: string;
};

type Props = {
    warehouseId: number;
    products: ProductOption[];
    onCancel: () => void;
};

let uidCounter = 0;

function nextUid(): string {
    uidCounter += 1;

    return `receipt-line-${uidCounter}`;
}

function emptyLine(): LineForm {
    return {
        uid: nextUid(),
        product_id: '',
        quantity: '1',
    };
}

export function StockReceiptForm({
    warehouseId,
    products,
    onCancel,
}: Props) {
    const form = useForm({
        received_at: new Date().toISOString().slice(0, 10),
        notes: '',
        lines: [emptyLine()],
    });

    const lines = form.data.lines as LineForm[];
    const lineErrors = form.errors as Record<string, string>;

    function setLines(next: LineForm[]) {
        form.setData('lines', next);
    }

    function updateLine(index: number, patch: Partial<LineForm>) {
        setLines(
            lines.map((line, i) => (i === index ? { ...line, ...patch } : line)),
        );
    }

    function addLine() {
        setLines([...lines, emptyLine()]);
    }

    function removeLine(index: number) {
        if (lines.length === 1) {
            return;
        }

        setLines(lines.filter((_, i) => i !== index));
    }

    function availableProducts(currentLineIndex: number): ProductOption[] {
        const usedIds = new Set(
            lines
                .filter((_, index) => index !== currentLineIndex)
                .map((line) => line.product_id)
                .filter(Boolean),
        );

        return products.filter(
            (product) => !usedIds.has(String(product.id)),
        );
    }

    const filledLines = useMemo(
        () =>
            lines.filter(
                (line) =>
                    line.product_id !== '' &&
                    Number(line.quantity) > 0,
            ),
        [lines],
    );

    const totalQuantity = filledLines.reduce(
        (sum, line) => sum + (Number(line.quantity) || 0),
        0,
    );

    const canSubmit = filledLines.length > 0 && !form.processing;

    function submit(event: FormEvent) {
        event.preventDefault();

        form.transform((data) => ({
            received_at: data.received_at,
            notes: data.notes || null,
            lines: (data.lines as LineForm[])
                .filter((line) => line.product_id !== '')
                .map((line) => ({
                    product_id: Number(line.product_id),
                    quantity: Number(line.quantity),
                })),
        }));

        form.post(WarehouseController.storeReceipt.url(warehouseId));
    }

    return (
        <form onSubmit={submit}>
            <div className="grid gap-6 lg:grid-cols-3">
                <div className="space-y-6 lg:col-span-2">
                    <Card>
                        <CardHeader>
                            <CardTitle>Informations générales</CardTitle>
                            <CardDescription>
                                Date et commentaires associés à cette entrée de
                                stock.
                            </CardDescription>
                        </CardHeader>
                        <CardContent className="space-y-4">
                            <div className="grid gap-4 sm:grid-cols-2">
                                <div className="grid gap-2">
                                    <Label htmlFor="received_at">
                                        Date de réception
                                        <span className="ml-0.5 text-destructive">
                                            *
                                        </span>
                                    </Label>
                                    <Input
                                        id="received_at"
                                        type="date"
                                        value={form.data.received_at}
                                        onChange={(event) =>
                                            form.setData(
                                                'received_at',
                                                event.target.value,
                                            )
                                        }
                                        required
                                    />
                                    <InputError
                                        message={form.errors.received_at}
                                    />
                                </div>
                            </div>

                            <div className="grid gap-2">
                                <Label htmlFor="notes">Notes</Label>
                                <Textarea
                                    id="notes"
                                    rows={3}
                                    placeholder="N° de bon de livraison, fournisseur, remarques… (optionnel)"
                                    value={form.data.notes}
                                    onChange={(event) =>
                                        form.setData(
                                            'notes',
                                            event.target.value,
                                        )
                                    }
                                />
                                <InputError message={form.errors.notes} />
                            </div>
                        </CardContent>
                    </Card>

                    <Card>
                        <CardHeader className="flex-row items-center justify-between space-y-0">
                            <div className="space-y-1.5">
                                <CardTitle>Produits reçus</CardTitle>
                                <CardDescription>
                                    {lines.length}{' '}
                                    {lines.length > 1 ? 'lignes' : 'ligne'} ·
                                    sélectionnez un produit et indiquez la
                                    quantité entrée.
                                </CardDescription>
                            </div>
                            <Button
                                type="button"
                                variant="outline"
                                size="sm"
                                onClick={addLine}
                                disabled={products.length === 0}
                            >
                                <Plus />
                                Ajouter
                            </Button>
                        </CardHeader>
                        <CardContent className="space-y-4">
                            {products.length === 0 ? (
                                <p className="text-muted-foreground rounded-lg border border-dashed py-8 text-center text-sm">
                                    Aucun produit disponible. Créez d&apos;abord
                                    des produits dans le catalogue.
                                </p>
                            ) : (
                                <>
                                    {lines.map((line, index) => {
                                        const product = products.find(
                                            (item) =>
                                                String(item.id) ===
                                                line.product_id,
                                        );
                                        const quantity =
                                            Number(line.quantity) || 0;

                                        return (
                                            <div
                                                key={line.uid}
                                                className="overflow-hidden rounded-xl border bg-background"
                                            >
                                                <div className="flex items-center justify-between gap-2 border-b bg-muted/40 px-4 py-2.5">
                                                    <div className="flex min-w-0 items-center gap-2.5">
                                                        <span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-primary/10 text-xs font-semibold text-primary">
                                                            {index + 1}
                                                        </span>
                                                        <span className="truncate text-sm font-medium">
                                                            {product
                                                                ? `${product.code} — ${product.name}`
                                                                : 'Nouvelle ligne'}
                                                        </span>
                                                        {product &&
                                                            quantity > 0 && (
                                                                <span className="text-muted-foreground shrink-0 text-xs tabular-nums">
                                                                    × {quantity}
                                                                </span>
                                                            )}
                                                    </div>
                                                    <Button
                                                        type="button"
                                                        variant="ghost"
                                                        size="icon"
                                                        className="size-8 shrink-0 text-muted-foreground hover:text-destructive"
                                                        onClick={() =>
                                                            removeLine(index)
                                                        }
                                                        disabled={
                                                            lines.length === 1
                                                        }
                                                        aria-label="Supprimer la ligne"
                                                    >
                                                        <Trash2 />
                                                    </Button>
                                                </div>

                                                <div className="grid gap-4 p-4 sm:grid-cols-2">
                                                    <div className="grid gap-2 sm:col-span-2">
                                                        <Label className="text-xs text-muted-foreground">
                                                            Produit
                                                            <span className="ml-0.5 text-destructive">
                                                                *
                                                            </span>
                                                        </Label>
                                                        <Select
                                                            value={
                                                                line.product_id ||
                                                                undefined
                                                            }
                                                            onValueChange={(
                                                                value,
                                                            ) =>
                                                                updateLine(
                                                                    index,
                                                                    {
                                                                        product_id:
                                                                            value,
                                                                    },
                                                                )
                                                            }
                                                        >
                                                            <SelectTrigger className="w-full">
                                                                <SelectValue placeholder="Choisir un produit…" />
                                                            </SelectTrigger>
                                                            <SelectContent>
                                                                {availableProducts(
                                                                    index,
                                                                ).map(
                                                                    (
                                                                        item,
                                                                    ) => (
                                                                        <SelectItem
                                                                            key={
                                                                                item.id
                                                                            }
                                                                            value={String(
                                                                                item.id,
                                                                            )}
                                                                        >
                                                                            {
                                                                                item.name
                                                                            }
                                                                            <span className="ml-2 text-xs text-muted-foreground">
                                                                                {
                                                                                    item.code
                                                                                }
                                                                            </span>
                                                                        </SelectItem>
                                                                    ),
                                                                )}
                                                            </SelectContent>
                                                        </Select>
                                                        <InputError
                                                            message={
                                                                lineErrors[
                                                                    `lines.${index}.product_id`
                                                                ]
                                                            }
                                                        />
                                                    </div>

                                                    <div className="grid gap-2">
                                                        <Label className="text-xs text-muted-foreground">
                                                            Quantité reçue
                                                        </Label>
                                                        <Input
                                                            type="number"
                                                            step="1"
                                                            min="1"
                                                            inputMode="numeric"
                                                            value={
                                                                line.quantity
                                                            }
                                                            onChange={(event) =>
                                                                updateLine(
                                                                    index,
                                                                    {
                                                                        quantity:
                                                                            event
                                                                                .target
                                                                                .value,
                                                                    },
                                                                )
                                                            }
                                                            required
                                                        />
                                                        <InputError
                                                            message={
                                                                lineErrors[
                                                                    `lines.${index}.quantity`
                                                                ]
                                                            }
                                                        />
                                                    </div>
                                                </div>
                                            </div>
                                        );
                                    })}

                                    <InputError message={form.errors.lines} />

                                    <Button
                                        type="button"
                                        variant="ghost"
                                        className="w-full border border-dashed text-muted-foreground hover:text-foreground"
                                        onClick={addLine}
                                    >
                                        <Plus />
                                        Ajouter une ligne
                                    </Button>
                                </>
                            )}
                        </CardContent>
                    </Card>
                </div>

                <div className="lg:col-span-1">
                    <Card className="lg:sticky lg:top-6">
                        <CardHeader>
                            <CardTitle>Récapitulatif</CardTitle>
                            <CardDescription>
                                Vérifiez les quantités avant d&apos;enregistrer
                                la réception.
                            </CardDescription>
                        </CardHeader>
                        <CardContent className="space-y-4">
                            <div className="flex items-center justify-between gap-4 text-sm">
                                <span className="text-muted-foreground">
                                    Date
                                </span>
                                <span className="font-medium tabular-nums">
                                    {form.data.received_at
                                        ? formatDate(form.data.received_at)
                                        : '—'}
                                </span>
                            </div>
                            <div className="flex items-center justify-between text-sm">
                                <span className="text-muted-foreground">
                                    Produits distincts
                                </span>
                                <span className="flex items-center gap-1.5 font-medium tabular-nums">
                                    <Package className="size-4 text-muted-foreground" />
                                    {filledLines.length}
                                </span>
                            </div>
                            <div className="flex items-center justify-between border-t pt-4">
                                <span className="text-sm font-medium">
                                    Total unités
                                </span>
                                <span className="text-xl font-semibold tabular-nums">
                                    {totalQuantity}
                                </span>
                            </div>

                            {filledLines.length > 0 && (
                                <ul className="text-muted-foreground space-y-1.5 border-t pt-4 text-xs">
                                    {filledLines.map((line) => {
                                        const product = products.find(
                                            (item) =>
                                                String(item.id) ===
                                                line.product_id,
                                        );

                                        if (!product) {
                                            return null;
                                        }

                                        return (
                                            <li
                                                key={line.uid}
                                                className="flex items-center justify-between gap-2"
                                            >
                                                <span className="truncate">
                                                    {product.code}
                                                </span>
                                                <span className="shrink-0 font-medium tabular-nums text-foreground">
                                                    {line.quantity}
                                                </span>
                                            </li>
                                        );
                                    })}
                                </ul>
                            )}

                            <div className="flex flex-col gap-2 pt-2">
                                <Button
                                    type="submit"
                                    disabled={!canSubmit}
                                >
                                    <PackagePlus />
                                    Enregistrer la réception
                                </Button>
                                <Button
                                    type="button"
                                    variant="outline"
                                    onClick={onCancel}
                                >
                                    Annuler
                                </Button>
                            </div>
                        </CardContent>
                    </Card>
                </div>
            </div>
        </form>
    );
}
