import { router } from '@inertiajs/react';
import { useEffect, useMemo, useState } from 'react';
import { toast } from 'sonner';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { ProductionFormulaMaterialsPreview } from '@/components/production/production-formula-materials-preview';
import { formatQuantityForInput, formatQuantityOrDash } from '@/lib/dates';
import { firstInertiaErrorMessage } from '@/lib/inertia-errors';
import {
    checkProductionMaterialStock,
    firstProductionStockError,
} from '@/lib/production-material-stock';
import { scaleFormulaMaterials } from '@/lib/production-formula';
import { cn } from '@/lib/utils';
import { zodErrorToNestedFieldMap } from '@/lib/zod-errors';
import { buildCompleteProductionOrderSchema } from '@/validation/schemas';

/**
 * @param {object} props
 * @param {boolean} props.open
 * @param {(open: boolean) => void} props.onOpenChange
 * @param {{ id: number, factory_product_id?: number, product_name?: string, unit_name?: string|null, quantity?: string, has_materials?: boolean } | null} props.order
 * @param {Record<string, { dough_quantity?: string, total_production?: string, materials?: Array<{ purchase_product_id: number, product_name?: string, quantity: string, quantity_unit?: string, unit_label?: string|null }> }>} props.productRecipes
 * @param {Array<{ id: number, name?: string, unit_name?: string|null, stock_on_hand?: string, stock_in_base?: string, factor_to_base?: string|number, uses_base_unit?: boolean }>} [props.rawProducts]
 * @param {Record<string, string>} props.labels
 * @param {Record<string, string>} props.validation
 * @param {Record<string, string>} props.appActions
 * @param {string} props.submitUrl
 * @param {string} props.locale
 */
export function ProductionCompleteDialog({
    open,
    onOpenChange,
    order,
    productRecipes = {},
    rawProducts = [],
    canViewProductionFormulas = false,
    labels,
    validation,
    appActions,
    submitUrl,
    locale,
}) {
    const [quantityProduced, setQuantityProduced] = useState('');
    const [errors, setErrors] = useState({});
    const [processing, setProcessing] = useState(false);

    const orderedQuantity = order?.quantity ?? '';
    const materialsLocked = order?.has_materials === true;

    const recipe = order?.factory_product_id
        ? productRecipes[String(order.factory_product_id)] ?? null
        : null;

    const schema = useMemo(
        () => buildCompleteProductionOrderSchema(validation),
        [validation],
    );

    useEffect(() => {
        if (open && order) {
            setQuantityProduced(formatQuantityForInput(order.quantity));
            setErrors({});
        }
    }, [open, order?.id, order?.quantity]);

    const effectiveQuantity = materialsLocked ? orderedQuantity : quantityProduced;

    const { materials: scaledMaterials, doughUsed } = useMemo(
        () => scaleFormulaMaterials(recipe, effectiveQuantity),
        [recipe, effectiveQuantity],
    );

    const surplusPreview = useMemo(() => {
        if (materialsLocked || !order?.customer_name) {
            return null;
        }

        const produced = Number.parseFloat(quantityProduced);
        const ordered = Number.parseFloat(orderedQuantity);

        if (!Number.isFinite(produced) || !Number.isFinite(ordered)) {
            return null;
        }

        return Math.max(0, produced - ordered);
    }, [materialsLocked, order?.customer_name, quantityProduced, orderedQuantity]);

    const hasFormula = Boolean(recipe?.materials?.length);
    const showFormulaDetails = canViewProductionFormulas;

    const stockCheck = useMemo(
        () =>
            showFormulaDetails
                ? checkProductionMaterialStock(scaledMaterials, rawProducts)
                : { sufficient: true, shortages: [] },
        [showFormulaDetails, scaledMaterials, rawProducts],
    );

    const stockLabels = useMemo(
        () => ({
            insufficientStockBanner: labels.insufficientStockBanner,
            insufficientStockFor: labels.insufficientStockFor,
            materialInStock: labels.materialInStock,
            materialStockShort: labels.materialStockShort,
        }),
        [labels],
    );

    function handleSubmit(e) {
        e.preventDefault();
        setErrors({});

        const parsed = schema.safeParse({
            quantity_produced: materialsLocked ? undefined : quantityProduced,
        });

        if (!parsed.success) {
            setErrors(zodErrorToNestedFieldMap(parsed.error));
            toast.error(validation.required ?? appActions.requestFailed);
            return;
        }

        if (showFormulaDetails && !hasFormula) {
            toast.error(labels.noFormulaDefined ?? appActions.requestFailed);
            return;
        }

        if (showFormulaDetails && !stockCheck.sufficient) {
            toast.error(firstProductionStockError(stockCheck.shortages, labels));
            return;
        }

        const payload = { materials: [] };

        if (!materialsLocked && parsed.data.quantity_produced != null) {
            payload.quantity_produced = parsed.data.quantity_produced;
        }

        setProcessing(true);
        router.post(submitUrl, payload, {
            preserveScroll: true,
            onSuccess: () => onOpenChange(false),
            onError: (pageErrors) =>
                toast.error(firstInertiaErrorMessage(pageErrors, appActions.requestFailed)),
            onFinish: () => setProcessing(false),
        });
    }

    return (
        <Dialog open={open} onOpenChange={onOpenChange}>
            <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-2xl">
                <form onSubmit={handleSubmit}>
                    <DialogHeader>
                        <DialogTitle>{labels.completeDialogTitle}</DialogTitle>
                        <DialogDescription>
                            {labels.completeDialogDescription}
                        </DialogDescription>
                    </DialogHeader>

                    <div className="space-y-4 py-4">
                        <div className="rounded-lg border border-border p-3 text-sm">
                            <p className="font-medium">
                                {order?.product_name}
                                {order?.unit_name ? ` (${order.unit_name})` : ''}
                            </p>
                            {order?.customer_name ? (
                                <p className="text-muted-foreground">
                                    {labels.colCustomer}: {order.customer_name}
                                </p>
                            ) : null}
                            <p className="text-muted-foreground tabular-nums">
                                {labels.orderedQuantityLabel}:{' '}
                                {formatQuantityOrDash(orderedQuantity, locale)}
                            </p>
                        </div>

                        {materialsLocked ? (
                            <p className="text-muted-foreground text-sm">
                                {labels.productionQuantityLabel}:{' '}
                                {formatQuantityOrDash(orderedQuantity, locale)}
                            </p>
                        ) : (
                            <div className="space-y-2">
                                <Label htmlFor="order-quantity-produced">
                                    {labels.quantityProducedLabel}
                                </Label>
                                <Input
                                    id="order-quantity-produced"
                                    type="number"
                                    min="0"
                                    step="0.001"
                                    value={quantityProduced}
                                    aria-invalid={Boolean(errors.quantity_produced)}
                                    className={cn(errors.quantity_produced && 'border-destructive')}
                                    onChange={(e) => setQuantityProduced(e.target.value)}
                                />
                                {errors.quantity_produced ? (
                                    <p className="text-destructive text-sm">{errors.quantity_produced}</p>
                                ) : null}
                                {surplusPreview !== null && surplusPreview > 0 ? (
                                    <p className="text-muted-foreground text-sm tabular-nums">
                                        {labels.completeSurplusHint.replace(
                                            '{qty}',
                                            formatQuantityOrDash(String(surplusPreview), locale),
                                        )}
                                    </p>
                                ) : null}
                            </div>
                        )}

                        {showFormulaDetails ? (
                            <ProductionFormulaMaterialsPreview
                                materials={scaledMaterials}
                                doughUsed={doughUsed}
                                rawProducts={rawProducts}
                                stockLabels={stockLabels}
                                doughQuantityLabel={labels.doughUsedHint}
                                materialsSectionLabel={labels.materialsSection}
                                noFormulaMessage={labels.noFormulaDefined}
                                locale={locale}
                            />
                        ) : (
                            <div className="space-y-2 rounded-lg border border-border bg-muted/20 px-3 py-3 text-sm">
                                {doughUsed != null ? (
                                    <p className="font-medium tabular-nums">
                                        {labels.doughUsedHint.replace(
                                            '{qty}',
                                            formatQuantityOrDash(String(doughUsed), locale),
                                        )}
                                    </p>
                                ) : null}
                                <p className="text-muted-foreground">
                                    {labels.batchAutoFormulaHint}
                                </p>
                            </div>
                        )}
                    </div>

                    <DialogFooter>
                        <Button
                            type="button"
                            variant="outline"
                            onClick={() => onOpenChange(false)}
                            disabled={processing}
                        >
                            {appActions.cancel}
                        </Button>
                        <Button
                            type="submit"
                            disabled={
                                processing ||
                                (showFormulaDetails &&
                                    (!hasFormula || !stockCheck.sufficient))
                            }
                        >
                            {processing
                                ? labels.completingProduction
                                : labels.completeProduction}
                        </Button>
                    </DialogFooter>
                </form>
            </DialogContent>
        </Dialog>
    );
}
