import { useForm } from '@inertiajs/react';
import { useEffect, useMemo, useState } from 'react';
import { toast } from 'sonner';
import {
    storeAmount as storeCrumbledCakeAmountSale,
    updateAmount as updateCrumbledCakeAmountSale,
} from '@/actions/App/Http/Controllers/CrumbledCakeSaleController';
import { ConfirmActionDialog } from '@/components/confirm-action-dialog';
import { AppDateInput } from '@/components/ui/app-date-input';
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 { Textarea } from '@/components/ui/textarea';
import { formatMoneyAmountOrDash } from '@/lib/dates';
import { zodErrorToFieldMap } from '@/lib/zod-errors';
import { z } from 'zod';

function todayYmd() {
    const now = new Date();
    const y = now.getFullYear();
    const m = String(now.getMonth() + 1).padStart(2, '0');
    const d = String(now.getDate()).padStart(2, '0');
    return `${y}-${m}-${d}`;
}

function buildSchema(v) {
    return z.object({
        sold_at: z.string().trim().min(1, v.required),
        amount: z.coerce.number().gt(0, v.required),
        notes: z.union([z.string().trim().max(2000), z.literal('')]).optional(),
    });
}

/**
 * @param {object} props
 * @param {boolean} props.open
 * @param {(open: boolean) => void} props.onOpenChange
 * @param {object | null} props.sale
 * @param {Record<string, string>} props.labels
 * @param {Record<string, string>} props.validation
 * @param {Record<string, string>} props.appActions
 * @param {'en'|'fa'} props.locale
 * @param {Record<string, string|null|undefined>} [props.query]
 */
export function CrumbledCakeAmountSaleDialog({
    open,
    onOpenChange,
    sale = null,
    labels,
    validation,
    appActions,
    locale,
    query = {},
}) {
    const isEdit = sale != null;
    const form = useForm({
        sold_at: todayYmd(),
        amount: '',
        notes: '',
    });
    const [confirmOpen, setConfirmOpen] = useState(false);
    const schema = useMemo(() => buildSchema(validation), [validation]);

    useEffect(() => {
        if (!open) {
            form.reset();
            form.clearErrors();
            setConfirmOpen(false);
            return;
        }

        if (sale) {
            form.setData({
                sold_at: sale.sold_at ?? todayYmd(),
                amount: sale.amount ?? '',
                notes: sale.notes ?? '',
            });
        } else {
            form.setData({
                sold_at: todayYmd(),
                amount: '',
                notes: '',
            });
        }
        form.clearErrors();
        // eslint-disable-next-line react-hooks/exhaustive-deps -- Inertia form identity is unstable
    }, [open, sale]);

    function validateAndConfirm() {
        form.clearErrors();
        const parsed = schema.safeParse(form.data);
        if (!parsed.success) {
            form.setError(zodErrorToFieldMap(parsed.error));
            toast.error(validation.required ?? appActions.requestFailed);
            return;
        }
        setConfirmOpen(true);
    }

    function submit() {
        const parsed = schema.safeParse(form.data);
        if (!parsed.success) {
            form.setError(zodErrorToFieldMap(parsed.error));
            setConfirmOpen(false);
            return;
        }

        form.transform(() => ({
            sold_at: parsed.data.sold_at,
            amount: parsed.data.amount,
            notes: parsed.data.notes ?? '',
            date_from: query.date_from || undefined,
            date_to: query.date_to || undefined,
            search: query.search || undefined,
        }));

        const options = {
            preserveScroll: true,
            onSuccess: () => {
                setConfirmOpen(false);
                onOpenChange(false);
                toast.success(
                    isEdit ? labels.amountToastUpdated : labels.amountToastCreated,
                );
            },
            onError: () => {
                setConfirmOpen(false);
                toast.error(appActions.requestFailed);
            },
        };

        if (isEdit) {
            form.put(updateCrumbledCakeAmountSale.url(sale.id), options);
            return;
        }

        form.post(storeCrumbledCakeAmountSale.url(), options);
    }

    return (
        <>
            <Dialog open={open} onOpenChange={onOpenChange}>
                <DialogContent
                    className="max-h-[90vh] overflow-y-auto sm:max-w-md"
                    onOpenAutoFocus={(event) => event.preventDefault()}
                >
                    <DialogHeader>
                        <DialogTitle>
                            {isEdit
                                ? labels.amountEditDialogTitle
                                : labels.amountCreateDialogTitle}
                        </DialogTitle>
                        <DialogDescription>
                            {isEdit
                                ? labels.amountEditDialogSubtitle
                                : labels.amountCreateDialogSubtitle}
                        </DialogDescription>
                    </DialogHeader>

                    <div className="grid gap-4 py-2">
                        <div className="bg-muted/40 rounded-md border px-3 py-2 text-sm">
                            <span className="text-muted-foreground">{labels.saleTypeLabel}: </span>
                            <span className="font-medium">{labels.cashSaleLabel}</span>
                        </div>

                        <div className="space-y-2">
                            <Label htmlFor="crumbled_amount_sold_at">{labels.soldAtLabel}</Label>
                            <AppDateInput
                                id="crumbled_amount_sold_at"
                                value={form.data.sold_at}
                                onChange={(value) => form.setData('sold_at', value)}
                                locale={locale}
                                unlockCalendar
                                calendarZIndex={320}
                                invalid={Boolean(form.errors.sold_at)}
                            />
                            {form.errors.sold_at ? (
                                <p className="text-destructive text-sm">{form.errors.sold_at}</p>
                            ) : null}
                        </div>

                        <div className="space-y-2">
                            <Label htmlFor="crumbled_amount_value">{labels.amountLabel}</Label>
                            <Input
                                id="crumbled_amount_value"
                                type="number"
                                min="0"
                                step="0.01"
                                value={form.data.amount}
                                onChange={(event) => form.setData('amount', event.target.value)}
                            />
                            {form.errors.amount ? (
                                <p className="text-destructive text-sm">{form.errors.amount}</p>
                            ) : null}
                        </div>

                        <div className="bg-muted/40 rounded-md border px-3 py-2 text-sm">
                            <span className="text-muted-foreground">{labels.amountPreviewLabel}: </span>
                            <span className="font-medium">
                                {formatMoneyAmountOrDash(form.data.amount || 0, locale)}
                            </span>
                            <span className="text-muted-foreground ms-2">
                                ({labels.paymentStatusPaid})
                            </span>
                        </div>

                        <div className="space-y-2">
                            <Label htmlFor="crumbled_amount_notes">{labels.notesLabel}</Label>
                            <Textarea
                                id="crumbled_amount_notes"
                                value={form.data.notes}
                                onChange={(event) => form.setData('notes', event.target.value)}
                                rows={3}
                            />
                            {form.errors.notes ? (
                                <p className="text-destructive text-sm">{form.errors.notes}</p>
                            ) : null}
                        </div>

                        {form.errors.crumbled_cake_amount_sale ? (
                            <p className="text-destructive text-sm">
                                {form.errors.crumbled_cake_amount_sale}
                            </p>
                        ) : null}
                    </div>

                    <DialogFooter>
                        <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
                            {appActions.cancel}
                        </Button>
                        <Button
                            type="button"
                            onClick={validateAndConfirm}
                            disabled={form.processing}
                        >
                            {isEdit ? labels.saveChanges : labels.saveSale}
                        </Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>

            <ConfirmActionDialog
                open={confirmOpen}
                onOpenChange={setConfirmOpen}
                title={
                    isEdit
                        ? labels.amountConfirmUpdateTitle
                        : labels.amountConfirmCreateTitle
                }
                description={
                    isEdit
                        ? labels.amountConfirmUpdateBody
                        : labels.amountConfirmCreateBody
                }
                confirmLabel={appActions.confirm}
                cancelLabel={appActions.cancel}
                processing={form.processing}
                onConfirm={submit}
            />
        </>
    );
}
