import { useForm } from '@inertiajs/react';
import { useEffect, useMemo, useState } from 'react';
import { ConfirmActionDialog } from '@/components/confirm-action-dialog';
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 { Spinner } from '@/components/ui/spinner';
import { useLanguage } from '@/contexts/language-context';
import { formatEmployeeJoiningDateOrDash } from '@/lib/dates';
import { cn } from '@/lib/utils';
import { zodErrorToFieldMap } from '@/lib/zod-errors';
import { buildPermanentEmployeePunishmentSchema } from '@/validation/schemas';

/**
 * @param {object} props
 * @param {'create'|'edit'} props.mode
 * @param {object} [props.initial]
 * @param {string} props.submitUrl
 * @param {'post'|'put'} props.submitMethod
 * @param {Record<string, string>} props.labels
 * @param {string} props.submitLabel
 * @param {string} props.submittingLabel
 * @param {string} props.confirmTitle
 * @param {string} props.confirmBody
 * @param {string} props.cancelLabel
 * @param {(page: object) => void} [props.onSuccess]
 */
export function PermanentEmployeePunishmentForm({
    initial,
    submitUrl,
    submitMethod,
    labels,
    submitLabel,
    submittingLabel,
    confirmTitle,
    confirmBody,
    cancelLabel,
    onSuccess,
}) {
    const { t } = useLanguage();
    const v = t.validation;
    const schema = useMemo(() => buildPermanentEmployeePunishmentSchema(v), [v]);
    const [confirmOpen, setConfirmOpen] = useState(false);

    const form = useForm({
        effective_date: initial?.effective_date ?? '',
        amount: initial?.amount ?? '',
        reason: initial?.reason ?? '',
    });

    useEffect(() => {
        if (!initial) {
            return;
        }

        form.setData({
            effective_date: initial.effective_date ?? '',
            amount: initial.amount ?? '',
            reason: initial.reason ?? '',
        });
        // eslint-disable-next-line react-hooks/exhaustive-deps -- Inertia form identity is unstable
    }, [initial]);

    function validateClient() {
        const parsed = schema.safeParse(form.data);

        if (!parsed.success) {
            form.setError(zodErrorToFieldMap(parsed.error));

            return false;
        }

        form.clearErrors();

        return true;
    }

    function submit() {
        if (!validateClient()) {
            return;
        }

        const options = {
            preserveScroll: true,
            onSuccess: (page) => {
                setConfirmOpen(false);
                onSuccess?.(page);
            },
        };

        if (submitMethod === 'put') {
            form.put(submitUrl, options);
        } else {
            form.post(submitUrl, options);
        }
    }

    return (
        <>
            <ConfirmActionDialog
                open={confirmOpen}
                onOpenChange={setConfirmOpen}
                title={confirmTitle}
                description={confirmBody}
                confirmLabel={submitLabel}
                cancelLabel={cancelLabel}
                processing={form.processing}
                onConfirm={submit}
            />
            <form
                noValidate
                onSubmit={(e) => {
                    e.preventDefault();
                    if (!validateClient()) {
                        return;
                    }
                    setConfirmOpen(true);
                }}
                className="mx-auto flex w-full max-w-3xl flex-col gap-6"
            >
                <Card>
                    <CardHeader>
                        <CardTitle>{labels.sectionPunishment}</CardTitle>
                        <CardDescription>{labels.sectionPunishmentHint}</CardDescription>
                    </CardHeader>
                    <CardContent className="grid gap-6 sm:grid-cols-2">
                        <div className="space-y-2">
                            <Label htmlFor="effective_date">{labels.punishmentDate}</Label>
                            <AppDateInput
                                id="effective_date"
                                forceJalali
                                value={form.data.effective_date}
                                onChange={(value) => {
                                    form.setData('effective_date', value);
                                    if (form.errors.effective_date) {
                                        form.clearErrors('effective_date');
                                    }
                                }}
                                invalid={Boolean(form.errors.effective_date)}
                            />
                            {form.data.effective_date ? (
                                <p className="text-muted-foreground text-xs">
                                    {formatEmployeeJoiningDateOrDash(form.data.effective_date)}
                                </p>
                            ) : null}
                            {form.errors.effective_date ? (
                                <p className="text-destructive text-sm">
                                    {form.errors.effective_date}
                                </p>
                            ) : null}
                        </div>

                        <div className="space-y-2">
                            <Label htmlFor="punishment_amount">{labels.punishmentAmount}</Label>
                            <Input
                                id="punishment_amount"
                                type="number"
                                min="0"
                                step="0.01"
                                value={form.data.amount}
                                onChange={(e) => {
                                    form.setData('amount', e.target.value);
                                    if (form.errors.amount) {
                                        form.clearErrors('amount');
                                    }
                                }}
                                aria-invalid={Boolean(form.errors.amount)}
                                className={cn(form.errors.amount && 'border-destructive')}
                            />
                            {form.errors.amount ? (
                                <p className="text-destructive text-sm">{form.errors.amount}</p>
                            ) : null}
                        </div>

                        <div className="space-y-2 sm:col-span-2">
                            <Label htmlFor="punishment_reason">{labels.punishmentReason}</Label>
                            <textarea
                                id="punishment_reason"
                                value={form.data.reason}
                                onChange={(e) => {
                                    form.setData('reason', e.target.value);
                                    if (form.errors.reason) {
                                        form.clearErrors('reason');
                                    }
                                }}
                                rows={4}
                                placeholder={labels.reasonPlaceholder}
                                className={cn(
                                    'border-input placeholder:text-muted-foreground flex min-h-[6rem] w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none md:text-sm',
                                    'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
                                    form.errors.reason && 'border-destructive',
                                )}
                            />
                            {form.errors.reason ? (
                                <p className="text-destructive text-sm">{form.errors.reason}</p>
                            ) : null}
                        </div>
                    </CardContent>
                </Card>

                <Button type="submit" disabled={form.processing} className="w-fit">
                    {form.processing ? (
                        <>
                            <Spinner className="size-4" />
                            {submittingLabel}
                        </>
                    ) : (
                        submitLabel
                    )}
                </Button>
            </form>
        </>
    );
}
