import { router, useForm } from '@inertiajs/react';
import { useCallback, useMemo, useState } from 'react';
import { toast } from 'sonner';
import { ConfirmActionDialog } from '@/components/confirm-action-dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { formatMoneyAmountOrDash, formatPurchaseCurrencyLabel } from '@/lib/dates';
import { zodErrorToFieldMap } from '@/lib/zod-errors';
import { buildApplySupplierCreditSchema } from '@/validation/schemas';

/**
 * @param {object} props
 * @param {Record<string, string>} props.labels
 * @param {Record<string, string>} props.validation
 * @param {Record<string, string>} props.appActions
 * @param {'en'|'fa'} props.locale
 * @param {Array<string>} props.currencies
 * @param {Array<object>} props.summaries
 * @param {Array<object>} props.openPurchases
 * @param {string} props.submitUrl
 */
export function SupplierApplyCreditForm({
    labels,
    validation,
    appActions,
    locale,
    currencies,
    summaries,
    openPurchases,
    submitUrl,
}) {
    const [currency, setCurrency] = useState(currencies[0] ?? 'afn');
    const [amounts, setAmounts] = useState({});
    const [confirmOpen, setConfirmOpen] = useState(false);
    const form = useForm({});

    const schema = useMemo(
        () => buildApplySupplierCreditSchema(validation),
        [validation],
    );

    const summary = useMemo(
        () => summaries.find((row) => row.currency === currency),
        [summaries, currency],
    );

    const bills = useMemo(
        () => openPurchases.filter((bill) => bill.currency === currency && bill.due_amount > 0),
        [openPurchases, currency],
    );

    const allocationRows = useMemo(() => {
        return bills
            .map((bill) => {
                const raw = amounts[bill.id];
                const amount = raw === '' || raw == null ? '' : String(raw);

                return {
                    purchase_id: bill.id,
                    bill_number: bill.bill_number,
                    due_amount: bill.due_amount,
                    amount,
                };
            })
            .filter((row) => row.amount !== '' && Number(row.amount) > 0);
    }, [bills, amounts]);

    const allocationTotal = useMemo(
        () =>
            allocationRows.reduce((sum, row) => sum + (Number(row.amount) || 0), 0),
        [allocationRows],
    );

    const setAmount = useCallback((purchaseId, value) => {
        setAmounts((prev) => ({ ...prev, [purchaseId]: value }));
    }, []);

    function buildPayload() {
        return {
            currency,
            allocations: allocationRows.map((row) => ({
                purchase_id: row.purchase_id,
                amount: row.amount,
            })),
        };
    }

    function handleSubmit(e) {
        e.preventDefault();
        const parsed = schema.safeParse(buildPayload());
        if (!parsed.success) {
            toast.error(zodErrorToFieldMap(parsed.error).allocations ?? appActions.requestFailed);
            return;
        }
        setConfirmOpen(true);
    }

    function commitApply() {
        const parsed = schema.safeParse(buildPayload());
        if (!parsed.success) {
            setConfirmOpen(false);
            return;
        }

        router.post(submitUrl, parsed.data, {
            preserveScroll: true,
            onError: () => toast.error(appActions.requestFailed),
            onFinish: () => setConfirmOpen(false),
        });
    }

    const availableCredit = summary?.unallocated_credit ?? 0;

    if (availableCredit <= 0) {
        return null;
    }

    return (
        <>
            <ConfirmActionDialog
                open={confirmOpen}
                onOpenChange={setConfirmOpen}
                title={labels.confirmApplyTitle}
                description={labels.confirmApplyBody}
                confirmLabel={labels.applyCredit}
                cancelLabel={appActions.cancel}
                processing={form.processing}
                onConfirm={commitApply}
            />

            <form onSubmit={handleSubmit} className="space-y-4 rounded-xl border border-border p-4">
                <div>
                    <h3 className="text-sm font-semibold">{labels.applyCreditSection}</h3>
                    <p className="text-muted-foreground text-sm">{labels.applyCreditSectionHint}</p>
                </div>

                <div className="grid gap-4 sm:grid-cols-2">
                    <div className="space-y-2">
                        <Label>{labels.currency}</Label>
                        <Select
                            value={currency}
                            onValueChange={(value) => {
                                setCurrency(value);
                                setAmounts({});
                            }}
                        >
                            <SelectTrigger>
                                <SelectValue />
                            </SelectTrigger>
                            <SelectContent>
                                {currencies.map((item) => (
                                    <SelectItem key={item} value={item}>
                                        {formatPurchaseCurrencyLabel(item, locale)}
                                    </SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                    </div>
                    <div className="space-y-1 text-sm">
                        <p className="text-muted-foreground">{labels.availableCredit}</p>
                        <p className="text-lg font-semibold tabular-nums">
                            {formatMoneyAmountOrDash(availableCredit, locale)}
                        </p>
                    </div>
                </div>

                {bills.length === 0 ? (
                    <p className="text-muted-foreground text-sm">{labels.noOpenBills}</p>
                ) : (
                    <div className="space-y-3">
                        {bills.map((bill) => (
                            <div
                                key={bill.id}
                                className="grid gap-3 rounded-lg border border-border p-3 sm:grid-cols-[1fr_auto]"
                            >
                                <div>
                                    <p className="font-medium">{bill.bill_number}</p>
                                    <p className="text-muted-foreground text-xs">
                                        {labels.dueLabel}:{' '}
                                        {formatMoneyAmountOrDash(bill.due_amount, locale)}
                                    </p>
                                </div>
                                <Input
                                    type="number"
                                    min="0"
                                    step="0.01"
                                    max={Math.min(bill.due_amount, availableCredit)}
                                    value={amounts[bill.id] ?? ''}
                                    onChange={(e) => setAmount(bill.id, e.target.value)}
                                    placeholder={labels.allocationPlaceholder}
                                    className="h-9"
                                />
                            </div>
                        ))}
                    </div>
                )}

                <div className="text-sm">
                    <span className="text-muted-foreground">{labels.creditToApply}: </span>
                    <span className="font-medium tabular-nums">
                        {formatMoneyAmountOrDash(allocationTotal, locale)}
                    </span>
                </div>

                <Button type="submit" variant="outline" disabled={allocationTotal <= 0}>
                    {labels.applyCredit}
                </Button>
            </form>
        </>
    );
}
