import { useForm } from '@inertiajs/react';
import { useEffect, useMemo, useState } from 'react';
import { toast } from 'sonner';
import { AppDateInput } from '@/components/ui/app-date-input';
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 { Spinner } from '@/components/ui/spinner';
import { Textarea } from '@/components/ui/textarea';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { buildLoanFifoAllocationPreview } from '@/lib/customer-loan-fifo-allocations';
import { customerLoanPaymentMethodLabel } from '@/lib/customer-loan-labels';
import { formatExpenseDateNumericOrDash } from '@/lib/dates';
import { formatDueForInput, parseMoneyInput } from '@/lib/money';
import { cn } from '@/lib/utils';
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}`;
}

export function CustomerLoanOverallRepaymentForm({
    customer,
    loanSummary,
    openLoans = [],
    paymentMethods = ['cash', 'bank', 'other'],
    labels,
    validation,
    submitUrl,
}) {
    const fullDueAmount = useMemo(() => {
        const fromSummary = formatDueForInput(loanSummary?.outstanding);

        if (fromSummary) {
            return fromSummary;
        }

        const total = openLoans.reduce(
            (sum, loan) => sum + (parseMoneyInput(loan.due_amount) ?? 0),
            0,
        );

        return formatDueForInput(total);
    }, [loanSummary?.outstanding, openLoans]);

    const [amount, setAmount] = useState(fullDueAmount);

    useEffect(() => {
        setAmount(fullDueAmount);
    }, [fullDueAmount, customer?.id]);

    const schema = useMemo(
        () =>
            z.object({
                paid_at: z.string().min(1, validation.required),
                amount: z.coerce.number().positive(validation.positiveNumber),
                payment_method: z.string().optional(),
                notes: z.string().optional(),
            }),
        [validation.positiveNumber, validation.required],
    );

    const form = useForm({
        paid_at: todayYmd(),
        amount: fullDueAmount,
        payment_method: 'cash',
        notes: '',
    });

    const fifoPreview = useMemo(() => {
        const enteredAmount = parseMoneyInput(amount);

        if (enteredAmount == null || enteredAmount <= 0) {
            return null;
        }

        return buildLoanFifoAllocationPreview(openLoans, enteredAmount);
    }, [amount, openLoans]);

    function payFullAmount() {
        setAmount(fullDueAmount);
    }

    function handleSubmit(e) {
        e.preventDefault();
        const payload = { ...form.data, amount };
        const parsed = schema.safeParse(payload);

        if (!parsed.success) {
            form.clearErrors();
            form.setError(zodErrorToFieldMap(parsed.error));
            return;
        }

        form.transform(() => payload);
        form.post(submitUrl, {
            onError: () => toast.error(labels.requestFailed),
        });
    }

    return (
        <form noValidate onSubmit={handleSubmit} className="mx-auto flex w-full max-w-3xl flex-col gap-6">
            <Card>
                <CardHeader>
                    <CardTitle>{labels.overallRepaymentTitle}</CardTitle>
                    <CardDescription>{labels.overallRepaymentDescription}</CardDescription>
                </CardHeader>
                <CardContent className="space-y-6">
                    <div className="rounded-lg border bg-muted/20 px-4 py-3">
                        <p className="text-muted-foreground text-sm">{labels.colCustomer}</p>
                        <p className="font-semibold">{customer?.full_name}</p>
                    </div>

                    <div className="rounded-lg border border-amber-200 bg-amber-50/50 px-4 py-4 dark:border-amber-900 dark:bg-amber-950/30">
                        <p className="text-muted-foreground text-sm">{labels.totalLoansDue}</p>
                        <p className="text-2xl font-semibold tabular-nums text-amber-700 dark:text-amber-400">
                            {loanSummary?.outstanding ?? '0.00'} {labels.currencyLabel}
                        </p>
                        <p className="text-muted-foreground mt-1 text-xs">{labels.totalLoansDueHint}</p>
                    </div>

                    {openLoans.length > 0 ? (
                        <div className="space-y-2">
                            <p className="text-sm font-medium">{labels.openLoansSection}</p>
                            <div className="rounded-md border">
                                <Table>
                                    <TableHeader>
                                        <TableRow>
                                            <TableHead>{labels.colLoanNumber}</TableHead>
                                            <TableHead>{labels.colDate}</TableHead>
                                            <TableHead className="text-end">{labels.colOutstanding}</TableHead>
                                        </TableRow>
                                    </TableHeader>
                                    <TableBody>
                                        {openLoans.map((loan) => (
                                            <TableRow key={loan.id}>
                                                <TableCell className="font-medium">{loan.loan_number}</TableCell>
                                                <TableCell>
                                                    {formatExpenseDateNumericOrDash(loan.loan_date)}
                                                </TableCell>
                                                <TableCell className="text-end tabular-nums">
                                                    {Number(loan.due_amount).toFixed(2)} {labels.currencyLabel}
                                                </TableCell>
                                            </TableRow>
                                        ))}
                                    </TableBody>
                                </Table>
                            </div>
                        </div>
                    ) : null}

                    <div className="grid gap-4 sm:grid-cols-2">
                        <div className="space-y-2 sm:col-span-2">
                            <Label htmlFor="overall_amount">{labels.colAmount}</Label>
                            <div className="flex flex-wrap items-center gap-2">
                                <Input
                                    id="overall_amount"
                                    type="number"
                                    min="0.01"
                                    step="any"
                                    className={cn('max-w-xs text-lg', form.errors.amount && 'border-destructive')}
                                    value={amount}
                                    onChange={(e) => setAmount(e.target.value)}
                                />
                                <span className="text-muted-foreground text-sm">{labels.currencyLabel}</span>
                                {fullDueAmount ? (
                                    <Button type="button" variant="outline" size="sm" onClick={payFullAmount}>
                                        {labels.payFullAmount}
                                    </Button>
                                ) : null}
                            </div>
                            {form.errors.amount ? (
                                <p className="text-destructive text-sm">{form.errors.amount}</p>
                            ) : null}
                        </div>

                        <div className="space-y-2">
                            <Label htmlFor="overall_paid_at">{labels.colPaidAt}</Label>
                            <AppDateInput
                                id="overall_paid_at"
                                value={form.data.paid_at}
                                onChange={(value) => form.setData('paid_at', value)}
                                invalid={Boolean(form.errors.paid_at)}
                            />
                        </div>

                        <div className="space-y-2">
                            <Label>{labels.paymentMethod}</Label>
                            <Select
                                value={form.data.payment_method}
                                onValueChange={(value) => form.setData('payment_method', value)}
                            >
                                <SelectTrigger>
                                    <SelectValue />
                                </SelectTrigger>
                                <SelectContent>
                                    {paymentMethods.map((method) => (
                                        <SelectItem key={method} value={method}>
                                            {customerLoanPaymentMethodLabel(method, labels)}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                        </div>

                        <div className="space-y-2 sm:col-span-2">
                            <Label htmlFor="overall_notes">{labels.notes}</Label>
                            <Textarea
                                id="overall_notes"
                                rows={2}
                                value={form.data.notes}
                                onChange={(e) => form.setData('notes', e.target.value)}
                            />
                        </div>
                    </div>

                    {fifoPreview?.allocations?.length ? (
                        <div className="rounded-lg border bg-muted/20 p-4 text-sm">
                            <p className="mb-2 font-medium">{labels.allocationPreviewTitle}</p>
                            <ul className="space-y-1">
                                {fifoPreview.allocations.map(({ loan, amount: slice }) => (
                                    <li key={loan.id} className="flex justify-between gap-4">
                                        <span>{loan.loan_number}</span>
                                        <span className="tabular-nums">
                                            {slice.toFixed(2)} {labels.currencyLabel}
                                        </span>
                                    </li>
                                ))}
                            </ul>
                            {fifoPreview.remainingCredit > 0.001 ? (
                                <p className="text-muted-foreground mt-2 text-xs">
                                    {labels.allocationRemainingHint.replace(
                                        '{amount}',
                                        `${fifoPreview.remainingCredit.toFixed(2)} ${labels.currencyLabel}`,
                                    )}
                                </p>
                            ) : null}
                        </div>
                    ) : null}
                </CardContent>
            </Card>

            <div className="flex justify-end">
                <Button type="submit" disabled={form.processing || openLoans.length === 0}>
                    {form.processing ? (
                        <>
                            <Spinner className="me-2" />
                            {labels.savingRepayment}
                        </>
                    ) : (
                        labels.repayAllLoans
                    )}
                </Button>
            </div>
        </form>
    );
}
