import { Head, router } from '@inertiajs/react';
import { Ban, Plus, Trash2 } from 'lucide-react';
import { useMemo, useState } from 'react';
import { toast } from 'sonner';
import OrderController from '@/actions/App/Http/Controllers/OrderController';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
    DialogTrigger,
} 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 SubmitSpinner from '@/components/submit-spinner';
import { Textarea } from '@/components/ui/textarea';

const priceFormatter = new Intl.NumberFormat('fr-FR');

function formatFcfa(amount: number): string {
    return `${priceFormatter.format(amount)} FCFA`;
}

type OrderItem = {
    id: number;
    quantity: number;
    unit_price: number;
    notes: string | null;
    product: { id: number; name: string };
};

type Order = {
    id: number;
    type: 'dine_in' | 'takeaway' | 'phone';
    status:
        | 'pending'
        | 'preparing'
        | 'ready'
        | 'served'
        | 'completed'
        | 'cancelled';
    total: number;
    customer_phone: string | null;
    notes: string | null;
    table: { id: number; number: string } | null;
    server: { id: number; name: string };
    items: OrderItem[];
    created_at: string;
};

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

type TableOption = {
    id: number;
    number: string;
    status: string;
};

type Props = {
    orders: Order[];
    products: ProductOption[];
    tables: TableOption[];
};

const typeLabels: Record<Order['type'], string> = {
    dine_in: 'Sur place',
    takeaway: 'À emporter',
    phone: 'Téléphone / WhatsApp',
};

const statusLabels: Record<Order['status'], string> = {
    pending: 'En attente',
    preparing: 'En préparation',
    ready: 'Prête',
    served: 'Servie',
    completed: 'Terminée',
    cancelled: 'Annulée',
};

const statusBadgeVariant: Record<
    Order['status'],
    'default' | 'secondary' | 'outline' | 'destructive'
> = {
    pending: 'outline',
    preparing: 'secondary',
    ready: 'default',
    served: 'default',
    completed: 'secondary',
    cancelled: 'destructive',
};

export default function OrdersIndex({ orders, products, tables }: Props) {
    const [creating, setCreating] = useState(false);

    const cancel = (order: Order) => {
        router.post(
            OrderController.cancel.url(order.id),
            {},
            {
                preserveScroll: true,
                onError: (errors) =>
                    toast.error(
                        errors.domain ?? "Impossible d'annuler cette commande.",
                    ),
            },
        );
    };

    const complete = (order: Order) => {
        router.post(
            OrderController.complete.url(order.id),
            {},
            {
                preserveScroll: true,
                onError: (errors) =>
                    toast.error(errors.domain ?? 'Action impossible.'),
            },
        );
    };

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

            <div className="flex flex-1 flex-col gap-6 p-4">
                <div className="flex items-center justify-between">
                    <div>
                        <h1 className="text-xl font-semibold tracking-tight">
                            Commandes
                        </h1>
                        <p className="text-muted-foreground text-sm">
                            Suivez les commandes en cours et leur préparation.
                        </p>
                    </div>

                    <Dialog open={creating} onOpenChange={setCreating}>
                        <DialogTrigger asChild>
                            <Button disabled={products.length === 0}>
                                <Plus />
                                Nouvelle commande
                            </Button>
                        </DialogTrigger>
                        <DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-lg">
                            <NewOrderForm
                                products={products}
                                tables={tables}
                                onCreated={() => {
                                    setCreating(false);
                                    router.reload({ only: ['orders'] });
                                }}
                            />
                        </DialogContent>
                    </Dialog>
                </div>

                {orders.length === 0 ? (
                    <p className="text-muted-foreground text-sm">
                        Aucune commande pour le moment.
                    </p>
                ) : (
                    <div className="grid gap-4 lg:grid-cols-2 xl:grid-cols-3">
                        {orders.map((order) => (
                            <Card key={order.id}>
                                <CardHeader className="flex-row items-start justify-between">
                                    <div>
                                        <CardTitle className="text-base">
                                            Commande #{order.id}
                                        </CardTitle>
                                        <p className="text-muted-foreground text-xs">
                                            {typeLabels[order.type]}
                                            {order.table &&
                                                ` · Table ${order.table.number}`}
                                            {' · '}
                                            {order.server.name}
                                        </p>
                                    </div>
                                    <Badge
                                        variant={
                                            statusBadgeVariant[order.status]
                                        }
                                    >
                                        {statusLabels[order.status]}
                                    </Badge>
                                </CardHeader>
                                <CardContent className="space-y-3">
                                    <ul className="space-y-1 text-sm">
                                        {order.items.map((item) => (
                                            <li
                                                key={item.id}
                                                className="flex justify-between"
                                            >
                                                <span>
                                                    {item.quantity}×{' '}
                                                    {item.product.name}
                                                </span>
                                                <span className="text-muted-foreground">
                                                    {formatFcfa(
                                                        item.quantity *
                                                            item.unit_price,
                                                    )}
                                                </span>
                                            </li>
                                        ))}
                                    </ul>

                                    <div className="flex items-center justify-between border-t pt-2 text-sm font-medium">
                                        <span>Total</span>
                                        <span>{formatFcfa(order.total)}</span>
                                    </div>

                                    <div className="flex flex-wrap gap-2 pt-1">
                                        {order.status === 'served' && (
                                            <Button
                                                size="sm"
                                                variant="outline"
                                                onClick={() => complete(order)}
                                            >
                                                Terminer
                                            </Button>
                                        )}
                                        {!['completed', 'cancelled'].includes(
                                            order.status,
                                        ) && (
                                            <Button
                                                size="sm"
                                                variant="outline"
                                                onClick={() => cancel(order)}
                                            >
                                                <Ban />
                                                Annuler
                                            </Button>
                                        )}
                                    </div>
                                </CardContent>
                            </Card>
                        ))}
                    </div>
                )}
            </div>
        </>
    );
}

type CartLine = {
    productId: number;
    quantity: number;
};

function NewOrderForm({
    products,
    tables,
    onCreated,
}: {
    products: ProductOption[];
    tables: TableOption[];
    onCreated: () => void;
}) {
    const [type, setType] = useState<Order['type']>('takeaway');
    const [tableId, setTableId] = useState<string>('');
    const [customerPhone, setCustomerPhone] = useState('');
    const [notes, setNotes] = useState('');
    const [cart, setCart] = useState<CartLine[]>([]);
    const [processing, setProcessing] = useState(false);
    const [errors, setErrors] = useState<Record<string, string>>({});

    const freeTables = tables.filter((t) => t.status === 'free');

    const total = useMemo(() => {
        return cart.reduce((sum, line) => {
            const product = products.find((p) => p.id === line.productId);
            return sum + (product?.price ?? 0) * line.quantity;
        }, 0);
    }, [cart, products]);

    const addLine = () => {
        const firstAvailable = products.find(
            (p) => !cart.some((line) => line.productId === p.id),
        );
        if (!firstAvailable) return;
        setCart([...cart, { productId: firstAvailable.id, quantity: 1 }]);
    };

    const updateLine = (index: number, patch: Partial<CartLine>) => {
        setCart(
            cart.map((line, i) => (i === index ? { ...line, ...patch } : line)),
        );
    };

    const removeLine = (index: number) => {
        setCart(cart.filter((_, i) => i !== index));
    };

    const submit = () => {
        setProcessing(true);
        setErrors({});

        router.post(
            OrderController.store.url(),
            {
                type,
                restaurant_table_id: type === 'dine_in' ? tableId : null,
                customer_phone: customerPhone || null,
                notes: notes || null,
                items: cart.map((line) => ({
                    product_id: line.productId,
                    quantity: line.quantity,
                })),
            },
            {
                preserveScroll: true,
                onSuccess: () => onCreated(),
                onError: (validationErrors) => {
                    setErrors(validationErrors as Record<string, string>);
                    if (validationErrors.domain) {
                        toast.error(validationErrors.domain);
                    }
                },
                onFinish: () => setProcessing(false),
            },
        );
    };

    return (
        <>
            <DialogHeader>
                <DialogTitle>Nouvelle commande</DialogTitle>
                <DialogDescription>
                    Composez la commande à transmettre en cuisine ou au bar.
                </DialogDescription>
            </DialogHeader>

            <div className="grid gap-4 py-2">
                <div className="grid gap-2">
                    <Label htmlFor="type">Type de commande</Label>
                    <Select
                        value={type}
                        onValueChange={(value) =>
                            setType(value as Order['type'])
                        }
                    >
                        <SelectTrigger id="type" className="w-full">
                            <SelectValue />
                        </SelectTrigger>
                        <SelectContent>
                            <SelectItem value="dine_in">Sur place</SelectItem>
                            <SelectItem value="takeaway">À emporter</SelectItem>
                            <SelectItem value="phone">
                                Téléphone / WhatsApp
                            </SelectItem>
                        </SelectContent>
                    </Select>
                    {errors.type && (
                        <p className="text-sm text-red-600">{errors.type}</p>
                    )}
                </div>

                {type === 'dine_in' && (
                    <div className="grid gap-2">
                        <Label htmlFor="table">Table</Label>
                        <Select value={tableId} onValueChange={setTableId}>
                            <SelectTrigger id="table" className="w-full">
                                <SelectValue placeholder="Sélectionnez une table libre" />
                            </SelectTrigger>
                            <SelectContent>
                                {freeTables.map((t) => (
                                    <SelectItem
                                        key={t.id}
                                        value={t.id.toString()}
                                    >
                                        Table {t.number}
                                    </SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                        {errors.restaurant_table_id && (
                            <p className="text-sm text-red-600">
                                {errors.restaurant_table_id}
                            </p>
                        )}
                    </div>
                )}

                {type === 'phone' && (
                    <div className="grid gap-2">
                        <Label htmlFor="customer_phone">Numéro du client</Label>
                        <Input
                            id="customer_phone"
                            value={customerPhone}
                            onChange={(e) => setCustomerPhone(e.target.value)}
                            placeholder="Ex : 07 00 00 00 00"
                        />
                    </div>
                )}

                <div className="grid gap-2">
                    <div className="flex items-center justify-between">
                        <Label>Articles</Label>
                        <Button
                            type="button"
                            size="sm"
                            variant="outline"
                            onClick={addLine}
                            disabled={cart.length >= products.length}
                        >
                            <Plus />
                            Ajouter
                        </Button>
                    </div>

                    {cart.length === 0 && (
                        <p className="text-muted-foreground text-sm">
                            Ajoutez au moins un article.
                        </p>
                    )}

                    {cart.map((line, index) => (
                        <div key={index} className="flex items-center gap-2">
                            <Select
                                value={line.productId.toString()}
                                onValueChange={(value) =>
                                    updateLine(index, {
                                        productId: Number(value),
                                    })
                                }
                            >
                                <SelectTrigger className="flex-1">
                                    <SelectValue />
                                </SelectTrigger>
                                <SelectContent>
                                    {products.map((p) => (
                                        <SelectItem
                                            key={p.id}
                                            value={p.id.toString()}
                                        >
                                            {p.name} ({formatFcfa(p.price)})
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                            <Input
                                type="number"
                                min={1}
                                max={99}
                                value={line.quantity}
                                onChange={(e) =>
                                    updateLine(index, {
                                        quantity: Number(e.target.value),
                                    })
                                }
                                className="w-20"
                            />
                            <Button
                                type="button"
                                variant="ghost"
                                size="icon"
                                onClick={() => removeLine(index)}
                            >
                                <Trash2 />
                            </Button>
                        </div>
                    ))}
                    {errors.items && (
                        <p className="text-sm text-red-600">{errors.items}</p>
                    )}
                </div>

                <div className="grid gap-2">
                    <Label htmlFor="notes">
                        Notes{' '}
                        <span className="text-muted-foreground">
                            (facultatif)
                        </span>
                    </Label>
                    <Textarea
                        id="notes"
                        value={notes}
                        onChange={(e) => setNotes(e.target.value)}
                        rows={2}
                    />
                </div>

                <div className="flex items-center justify-between border-t pt-3 text-sm font-medium">
                    <span>Total</span>
                    <span>{formatFcfa(total)}</span>
                </div>
            </div>

            <DialogFooter>
                <Button
                    type="button"
                    onClick={submit}
                    disabled={processing || cart.length === 0}
                >
                    <SubmitSpinner show={processing} />
                    Enregistrer
                </Button>
            </DialogFooter>
        </>
    );
}
