import { useForm } from '@inertiajs/react';
import { Package, Plus, Trash2 } from 'lucide-react';
import type { FormEvent } from 'react';
import PurchaseOrderController from '@/actions/App/Http/Controllers/Admin/PurchaseOrderController';
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 { useCompanyCurrency } from '@/hooks/use-company-currency';
import { formatCurrency } from '@/lib/utils';

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

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

export type PurchaseOrderLineData = {
    id?: number;
    product_id: number | null;
    description: string;
    quantity: string | number;
    unit_price: string | number;
};

export type PurchaseOrderFormData = {
    id: number;
    code: string;
    supplier_id: number | null;
    order_date: string | null;
    expected_delivery_date: string | null;
    invoice_due_date: string | null;
    notes: string | null;
    lines: PurchaseOrderLineData[];
};

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

type Props = {
    suppliers: SupplierOption[];
    products: ProductOption[];
    order?: PurchaseOrderFormData | null;
    onCancel: () => void;
};

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

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

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

export function PurchaseOrderForm({
    suppliers,
    products,
    order = null,
    onCancel,
}: Props) {
    const isEditing = order !== null;
    const { symbol: currencySymbol } = useCompanyCurrency();

    const form = useForm({
        supplier_id: order?.supplier_id ? String(order.supplier_id) : '',
        order_date: order?.order_date ?? new Date().toISOString().slice(0, 10),
        expected_delivery_date: order?.expected_delivery_date ?? '',
        invoice_due_date: order?.invoice_due_date ?? '',
        notes: order?.notes ?? '',
        lines:
            order && order.lines.length > 0
                ? order.lines.map(
                      (line): LineForm => ({
                          uid: nextUid(),
                          product_id: line.product_id
                              ? String(line.product_id)
                              : '',
                          quantity: String(line.quantity),
                          unit_price: String(line.unit_price),
                      }),
                  )
                : [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));
    }

    const total = lines.reduce(
        (sum, line) =>
            sum + (Number(line.quantity) || 0) * (Number(line.unit_price) || 0),
        0,
    );

    const selectedSupplier = suppliers.find(
        (supplier) => String(supplier.id) === form.data.supplier_id,
    );

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

        const payload = {
            ...form.data,
            lines: lines.map((line) => ({
                product_id: line.product_id ? Number(line.product_id) : null,
                quantity: line.quantity,
                unit_price: line.unit_price,
            })),
        };

        form.transform(() => payload);

        if (isEditing && order) {
            form.put(PurchaseOrderController.update.url(order.id));

            return;
        }

        form.post(PurchaseOrderController.store.url());
    }

    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>
                                Choisissez le fournisseur et les échéances de la
                                commande.
                            </CardDescription>
                        </CardHeader>
                        <CardContent className="space-y-4">
                            {isEditing && order && (
                                <div className="grid max-w-xs gap-2">
                                    <Label htmlFor="po-code">Référence</Label>
                                    <Input
                                        id="po-code"
                                        value={order.code}
                                        disabled
                                        readOnly
                                        className="font-mono"
                                    />
                                </div>
                            )}

                            <div className="grid gap-2">
                                <Label htmlFor="po-supplier">
                                    Fournisseur
                                    <span className="ml-0.5 text-destructive">
                                        *
                                    </span>
                                </Label>
                                <Select
                                    value={form.data.supplier_id || undefined}
                                    onValueChange={(value) =>
                                        form.setData('supplier_id', value)
                                    }
                                >
                                    <SelectTrigger
                                        id="po-supplier"
                                        className="w-full"
                                    >
                                        <SelectValue placeholder="Choisir un fournisseur…" />
                                    </SelectTrigger>
                                    <SelectContent>
                                        {suppliers.map((supplier) => (
                                            <SelectItem
                                                key={supplier.id}
                                                value={String(supplier.id)}
                                            >
                                                {supplier.name}
                                                <span className="ml-2 text-xs text-muted-foreground">
                                                    {supplier.code}
                                                </span>
                                            </SelectItem>
                                        ))}
                                    </SelectContent>
                                </Select>
                                <InputError message={form.errors.supplier_id} />
                            </div>

                            <div className="grid gap-4 sm:grid-cols-3">
                                <div className="grid gap-2">
                                    <Label htmlFor="po-order-date">
                                        Date de commande
                                        <span className="ml-0.5 text-destructive">
                                            *
                                        </span>
                                    </Label>
                                    <Input
                                        id="po-order-date"
                                        type="date"
                                        value={form.data.order_date}
                                        onChange={(event) =>
                                            form.setData(
                                                'order_date',
                                                event.target.value,
                                            )
                                        }
                                        required
                                    />
                                    <InputError
                                        message={form.errors.order_date}
                                    />
                                </div>

                                <div className="grid gap-2">
                                    <Label htmlFor="po-delivery-date">
                                        Livraison prévue
                                    </Label>
                                    <Input
                                        id="po-delivery-date"
                                        type="date"
                                        value={form.data.expected_delivery_date}
                                        onChange={(event) =>
                                            form.setData(
                                                'expected_delivery_date',
                                                event.target.value,
                                            )
                                        }
                                    />
                                    <InputError
                                        message={
                                            form.errors.expected_delivery_date
                                        }
                                    />
                                </div>

                                <div className="grid gap-2">
                                    <Label htmlFor="po-invoice-date">
                                        Échéance facturation
                                    </Label>
                                    <Input
                                        id="po-invoice-date"
                                        type="date"
                                        value={form.data.invoice_due_date}
                                        onChange={(event) =>
                                            form.setData(
                                                'invoice_due_date',
                                                event.target.value,
                                            )
                                        }
                                    />
                                    <InputError
                                        message={form.errors.invoice_due_date}
                                    />
                                </div>
                            </div>

                            <div className="grid gap-2">
                                <Label htmlFor="po-notes">Notes</Label>
                                <Textarea
                                    id="po-notes"
                                    rows={3}
                                    placeholder="Informations complémentaires (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>Lignes de commande</CardTitle>
                                <CardDescription>
                                    {lines.length}{' '}
                                    {lines.length > 1 ? 'lignes' : 'ligne'} ·
                                    associez un produit ou saisissez une ligne
                                    libre.
                                </CardDescription>
                            </div>
                            <Button
                                type="button"
                                variant="outline"
                                size="sm"
                                onClick={addLine}
                            >
                                <Plus />
                                Ajouter
                            </Button>
                        </CardHeader>
                        <CardContent className="space-y-4">
                            {lines.map((line, index) => {
                                const subtotal =
                                    (Number(line.quantity) || 0) *
                                    (Number(line.unit_price) || 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 items-center gap-2.5">
                                                <span className="flex size-6 items-center justify-center rounded-full bg-primary/10 text-xs font-semibold text-primary">
                                                    {index + 1}
                                                </span>
                                                <span className="text-sm font-medium">
                                                    {subtotal > 0
                                                        ? formatCurrency(
                                                              subtotal,
                                                          )
                                                        : 'Nouvelle ligne'}
                                                </span>
                                            </div>
                                            <Button
                                                type="button"
                                                variant="ghost"
                                                size="icon"
                                                className="size-8 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>
                                                        {products.map(
                                                            (product) => (
                                                                <SelectItem
                                                                    key={
                                                                        product.id
                                                                    }
                                                                    value={String(
                                                                        product.id,
                                                                    )}
                                                                >
                                                                    {
                                                                        product.name
                                                                    }
                                                                    <span className="ml-2 text-xs text-muted-foreground">
                                                                        {
                                                                            product.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é
                                                </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 className="grid gap-2">
                                                <Label className="text-xs text-muted-foreground">
                                                    Prix unitaire ({currencySymbol})
                                                </Label>
                                                <Input
                                                    type="number"
                                                    step="1"
                                                    min="0"
                                                    inputMode="numeric"
                                                    placeholder="0"
                                                    value={line.unit_price}
                                                    onChange={(event) =>
                                                        updateLine(index, {
                                                            unit_price:
                                                                event.target
                                                                    .value,
                                                        })
                                                    }
                                                    required
                                                />
                                                <InputError
                                                    message={
                                                        lineErrors[
                                                            `lines.${index}.unit_price`
                                                        ]
                                                    }
                                                />
                                            </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 la commande avant d'enregistrer.
                            </CardDescription>
                        </CardHeader>
                        <CardContent className="space-y-4">
                            <div className="flex items-center justify-between gap-4 text-sm">
                                <span className="text-muted-foreground">
                                    Fournisseur
                                </span>
                                <span className="truncate text-right font-medium">
                                    {selectedSupplier?.name ?? '—'}
                                </span>
                            </div>
                            <div className="flex items-center justify-between text-sm">
                                <span className="text-muted-foreground">
                                    Nombre de lignes
                                </span>
                                <span className="flex items-center gap-1.5 font-medium tabular-nums">
                                    <Package className="size-4 text-muted-foreground" />
                                    {lines.length}
                                </span>
                            </div>
                            <div className="flex items-center justify-between border-t pt-4">
                                <span className="text-sm font-medium">
                                    Total
                                </span>
                                <span className="text-xl font-semibold tabular-nums">
                                    {formatCurrency(total)}
                                </span>
                            </div>

                            <div className="flex flex-col gap-2 pt-2">
                                <Button
                                    type="submit"
                                    disabled={form.processing}
                                >
                                    {isEditing
                                        ? 'Enregistrer les modifications'
                                        : 'Créer la commande'}
                                </Button>
                                <Button
                                    type="button"
                                    variant="outline"
                                    onClick={onCancel}
                                >
                                    Annuler
                                </Button>
                            </div>
                        </CardContent>
                    </Card>
                </div>
            </div>
        </form>
    );
}
