import { useForm } from '@inertiajs/react';
import { useMemo, useState } from 'react';
import { toast } from 'sonner';
import { ConfirmActionDialog } from '@/components/confirm-action-dialog';
import { Alert, AlertDescription } from '@/components/ui/alert';
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 { useLanguage } from '@/contexts/language-context';
import { formatExpenseDateLongOrDash } from '@/lib/dates';
import { expensePaymentLabel, expenseStatusLabel, expenseCategoryLabel } from '@/lib/expense-labels';
import { formatAfn } from '@/lib/money';
import { cn } from '@/lib/utils';
import { zodErrorToFieldMap } from '@/lib/zod-errors';
import { buildExpenseFormSchema } from '@/validation/schemas';

export function ExpenseForm({
    expenseDay,
    expense,
    categories,
    paymentMethods,
    statuses,
    submitUrl,
    method = 'post',
    isEdit = false,
    cancelHref,
}) {
    const { t } = useLanguage();
    const p = t.expensesPage;
    const a = t.appActions;
    const [confirmOpen, setConfirmOpen] = useState(false);

    const schema = useMemo(() => buildExpenseFormSchema(t.validation), [t.validation]);

    const form = useForm({
        expense_category_id: expense?.category_id ? String(expense.category_id) : '',
        amount_original: expense?.amount_original ?? '',
        payment_method: expense?.payment_method ?? 'cash',
        vendor_paid_to: expense?.vendor_paid_to ?? '',
        reference_number: expense?.reference_number ?? '',
        description: expense?.description ?? '',
        status: expense?.status ?? 'paid',
        attachments: [],
    });

    function handleSubmit(e) {
        e.preventDefault();
        const parsed = schema.safeParse(form.data);
        if (!parsed.success) {
            form.clearErrors();
            form.setError(zodErrorToFieldMap(parsed.error));
            return;
        }
        setConfirmOpen(true);
    }

    function commitSubmit() {
        const options = {
            forceFormData: true,
            preserveScroll: true,
            onError: () => toast.error(a.requestFailed),
            onFinish: () => setConfirmOpen(false),
        };

        if (method === 'put') {
            form.transform((data) => ({ ...data, _method: 'put' }));
            form.post(submitUrl, options);
            return;
        }

        form.post(submitUrl, options);
    }

    const amountPreview = formatAfn(form.data.amount_original || 0);

    return (
        <>
            <ConfirmActionDialog
                open={confirmOpen}
                onOpenChange={setConfirmOpen}
                title={isEdit ? p.confirmUpdateTitle : p.confirmSaveTitle}
                description={isEdit ? p.confirmUpdateBody : p.confirmSaveBody}
                confirmLabel={isEdit ? p.saveExpense : p.saveExpense}
                cancelLabel={p.cancel}
                processing={form.processing}
                onConfirm={commitSubmit}
            />
            <form
                noValidate
                onSubmit={handleSubmit}
                className="mx-auto flex w-full max-w-3xl flex-col gap-6"
            >
                <Alert>
                    <AlertDescription>
                        {p.recordedForDate.replace('{date}', formatExpenseDateLongOrDash(expenseDay.expense_date))}
                    </AlertDescription>
                </Alert>

                <Card>
                    <CardHeader>
                        <CardTitle>{p.sectionDetails}</CardTitle>
                    </CardHeader>
                    <CardContent className="grid gap-5 sm:grid-cols-2">
                        <div className="space-y-2 sm:col-span-2">
                            <Label>{p.category}</Label>
                            <Select
                                value={form.data.expense_category_id}
                                onValueChange={(value) => form.setData('expense_category_id', value)}
                            >
                                <SelectTrigger className={cn(form.errors.expense_category_id && 'border-destructive')}>
                                    <SelectValue placeholder={p.category} />
                                </SelectTrigger>
                                <SelectContent>
                                    {categories.map((category) => (
                                        <SelectItem key={category.id} value={String(category.id)}>
                                            {expenseCategoryLabel(category.slug, category.name, p)}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                            {form.errors.expense_category_id ? (
                                <p className="text-destructive text-sm">{form.errors.expense_category_id}</p>
                            ) : null}
                        </div>
                        <div className="space-y-2">
                            <Label>{p.status}</Label>
                            <Select
                                value={form.data.status}
                                onValueChange={(value) => form.setData('status', value)}
                            >
                                <SelectTrigger>
                                    <SelectValue />
                                </SelectTrigger>
                                <SelectContent>
                                    {statuses.map((status) => (
                                        <SelectItem key={status.value} value={status.value}>
                                            {expenseStatusLabel(status.value, p)}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                        </div>
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>{p.sectionPayment}</CardTitle>
                    </CardHeader>
                    <CardContent className="grid gap-5 sm:grid-cols-2">
                        <div className="space-y-2 sm:col-span-2">
                            <Label htmlFor="amount_original">{p.amount}</Label>
                            <div className="flex items-center gap-3">
                                <Input
                                    id="amount_original"
                                    type="number"
                                    min="0.01"
                                    step="any"
                                    className={cn('text-lg', form.errors.amount_original && 'border-destructive')}
                                    value={form.data.amount_original}
                                    onChange={(e) => form.setData('amount_original', e.target.value)}
                                />
                                <span className="text-muted-foreground text-sm font-medium">{p.currencyLabel}</span>
                            </div>
                            <p className="text-muted-foreground text-xs">{amountPreview}</p>
                            {form.errors.amount_original ? (
                                <p className="text-destructive text-sm">{form.errors.amount_original}</p>
                            ) : null}
                        </div>
                        <div className="space-y-2 sm:col-span-2">
                            <Label>{p.paymentMethod}</Label>
                            <Select
                                value={form.data.payment_method}
                                onValueChange={(value) => form.setData('payment_method', value)}
                            >
                                <SelectTrigger>
                                    <SelectValue />
                                </SelectTrigger>
                                <SelectContent>
                                    {paymentMethods.map((methodOption) => (
                                        <SelectItem key={methodOption.value} value={methodOption.value}>
                                            {expensePaymentLabel(methodOption.value, p)}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                        </div>
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>{p.sectionVendor}</CardTitle>
                    </CardHeader>
                    <CardContent className="grid gap-5 sm:grid-cols-2">
                        <div className="space-y-2">
                            <Label htmlFor="vendor_paid_to">{p.vendorPaidTo}</Label>
                            <Input
                                id="vendor_paid_to"
                                value={form.data.vendor_paid_to}
                                onChange={(e) => form.setData('vendor_paid_to', e.target.value)}
                            />
                        </div>
                        <div className="space-y-2">
                            <Label htmlFor="reference_number">{p.referenceNumber}</Label>
                            <Input
                                id="reference_number"
                                value={form.data.reference_number}
                                onChange={(e) => form.setData('reference_number', e.target.value)}
                            />
                        </div>
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>{p.sectionNotes}</CardTitle>
                        <CardDescription>{p.attachments}</CardDescription>
                    </CardHeader>
                    <CardContent className="space-y-5">
                        <div className="space-y-2">
                            <Label htmlFor="description">{p.description}</Label>
                            <Textarea
                                id="description"
                                rows={4}
                                value={form.data.description}
                                onChange={(e) => form.setData('description', e.target.value)}
                            />
                        </div>
                        <div className="space-y-2">
                            <Label htmlFor="attachments">{p.attachments}</Label>
                            <Input
                                id="attachments"
                                type="file"
                                multiple
                                accept="image/jpeg,image/png,image/webp,application/pdf,.jpg,.jpeg,.png,.webp,.pdf"
                                className="cursor-pointer"
                                onChange={(e) =>
                                    form.setData('attachments', Array.from(e.target.files ?? []))
                                }
                            />
                        </div>
                    </CardContent>
                </Card>

                <div className="flex flex-wrap justify-end gap-3">
                    <Button type="button" variant="outline" asChild>
                        <a href={cancelHref}>{p.cancel}</a>
                    </Button>
                    <Button type="submit" disabled={form.processing}>
                        {form.processing ? (
                            <>
                                <Spinner className="me-2" />
                                {p.savingExpense}
                            </>
                        ) : (
                            p.saveExpense
                        )}
                    </Button>
                </div>
            </form>
        </>
    );
}
