import { useForm } from '@inertiajs/react';
import { useEffect, useMemo, useState } from 'react';
import { toast } from 'sonner';
import { ConfirmActionDialog } from '@/components/confirm-action-dialog';
import { EmployeePhoto } from '@/components/employees/employee-photo';
import { StorageFilePreview } from '@/components/employees/storage-file-preview';
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 { Switch } from '@/components/ui/switch';
import { useLanguage } from '@/contexts/language-context';
import { useInitials } from '@/hooks/use-initials';
import { isImageFileUrl, resolveStorageUrl } from '@/lib/storage-files';
import { cn } from '@/lib/utils';
import { zodErrorToFieldMap } from '@/lib/zod-errors';
import { buildCustomerSchema } from '@/validation/schemas';

function FileField({ id, label, hint, accept, error, currentUrl, currentLabel, onChange }) {
    const [pickedPreview, setPickedPreview] = useState(null);

    useEffect(() => {
        return () => {
            if (pickedPreview?.startsWith('blob:')) {
                URL.revokeObjectURL(pickedPreview);
            }
        };
    }, [pickedPreview]);

    function handleChange(e) {
        const file = e.target.files?.[0] ?? null;

        setPickedPreview((prev) => {
            if (prev?.startsWith('blob:')) {
                URL.revokeObjectURL(prev);
            }
            if (file?.type.startsWith('image/')) {
                return URL.createObjectURL(file);
            }
            return null;
        });

        onChange(e);
    }

    const previewUrl =
        pickedPreview ?? (currentUrl && isImageFileUrl(currentUrl) ? currentUrl : null);

    return (
        <div className="space-y-2">
            <Label htmlFor={id}>{label}</Label>
            {previewUrl ? (
                <StorageFilePreview
                    url={previewUrl}
                    alt={label}
                    linkLabel={currentLabel}
                    size="md"
                />
            ) : currentUrl ? (
                <StorageFilePreview
                    url={currentUrl}
                    alt={label}
                    linkLabel={currentLabel}
                    size="md"
                />
            ) : null}
            <Input
                id={id}
                name={id}
                type="file"
                accept={accept}
                className="cursor-pointer text-sm file:me-3 file:rounded-md file:border-0 file:bg-muted file:px-3 file:py-1.5 file:text-sm file:font-medium"
                onChange={handleChange}
            />
            {hint ? <p className="text-muted-foreground text-xs">{hint}</p> : null}
            {error ? <p className="text-destructive text-sm">{error}</p> : null}
        </div>
    );
}

/**
 * @param {object} props
 * @param {'create' | 'edit'} props.mode
 * @param {Record<string, string>} props.labels
 * @param {object} [props.customer]
 * @param {string} props.submitUrl
 * @param {'post' | 'put'} props.submitMethod
 * @param {string} props.submitLabel
 * @param {string} props.submittingLabel
 * @param {() => void} [props.onSuccess]
 */
export function CustomerForm({
    mode,
    labels,
    customer,
    submitUrl,
    submitMethod,
    submitLabel,
    submittingLabel,
    onSuccess,
}) {
    const { t } = useLanguage();
    const p = t.customersPage;
    const a = t.appActions;
    const getInitials = useInitials();
    const isEdit = mode === 'edit';
    const [confirmOpen, setConfirmOpen] = useState(false);

    const schema = useMemo(
        () => buildCustomerSchema(t.validation),
        [t.validation],
    );

    const form = useForm({
        full_name: customer?.full_name ?? '',
        national_card_number: customer?.national_card_number ?? '',
        address: customer?.address ?? '',
        supply_zone: customer?.supply_zone ?? '',
        contact_number: customer?.contact_number ?? '',
        is_active: customer?.is_active ?? true,
        image: null,
        national_card: null,
        car_image: null,
    });

    const [imagePreview, setImagePreview] = useState(
        () => resolveStorageUrl(customer?.image_url) ?? null,
    );

    useEffect(() => {
        return () => {
            if (imagePreview?.startsWith('blob:')) {
                URL.revokeObjectURL(imagePreview);
            }
        };
    }, [imagePreview]);

    const initials = getInitials(form.data.full_name || '?');

    function onImageChange(e) {
        const file = e.target.files?.[0] ?? null;
        form.setData('image', file);
        setImagePreview((prev) => {
            if (prev?.startsWith('blob:')) {
                URL.revokeObjectURL(prev);
            }
            return file
                ? URL.createObjectURL(file)
                : resolveStorageUrl(customer?.image_url);
        });
    }

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

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

        return parsed.data;
    }

    function handleSubmit(e) {
        e.preventDefault();
        form.clearErrors();

        if (!buildValidatedPayload()) {
            return;
        }

        setConfirmOpen(true);
    }

    function commitSubmit() {
        form.clearErrors();

        if (!buildValidatedPayload()) {
            setConfirmOpen(false);
            return;
        }

        const options = {
            forceFormData: true,
            preserveScroll: true,
            onSuccess,
            onError: () => toast.error(a.requestFailed),
        };

        if (submitMethod === 'post') {
            form.post(submitUrl, options);
        } else {
            form.transform((data) => ({ ...data, _method: 'put' }));
            form.post(submitUrl, options);
        }
    }

    const textareaClassName = 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.address && 'border-destructive',
    );

    return (
        <>
            <ConfirmActionDialog
                open={confirmOpen}
                onOpenChange={setConfirmOpen}
                title={isEdit ? p.confirmUpdateTitle : p.confirmCreateTitle}
                description={isEdit ? p.confirmUpdateBody : p.confirmCreateBody}
                confirmLabel={submitLabel}
                cancelLabel={a.cancel}
                processing={form.processing}
                onConfirm={commitSubmit}
            />
            <form
                noValidate
                onSubmit={handleSubmit}
                className="mx-auto flex w-full max-w-3xl flex-col gap-6"
            >
                <Card>
                    <CardHeader>
                        <CardTitle>{labels.sectionPersonal}</CardTitle>
                        <CardDescription>{labels.sectionPersonalHint}</CardDescription>
                    </CardHeader>
                    <CardContent className="space-y-5">
                        <div className="space-y-3">
                            <Label>{labels.customerImage}</Label>
                            <div className="flex flex-col items-start gap-4 sm:flex-row sm:items-center">
                                <EmployeePhoto
                                    src={imagePreview}
                                    initials={initials}
                                    size="lg"
                                />
                                <div className="grid w-full max-w-md gap-2">
                                    <Input
                                        id="image"
                                        name="image"
                                        type="file"
                                        accept="image/jpeg,image/png,image/webp,.jpg,.jpeg,.png,.webp"
                                        className="cursor-pointer text-sm file:me-3 file:rounded-md file:border-0 file:bg-muted file:px-3 file:py-1.5 file:text-sm file:font-medium"
                                        onChange={onImageChange}
                                    />
                                    <p className="text-muted-foreground text-xs">{labels.imageHint}</p>
                                    {form.errors.image ? (
                                        <p className="text-destructive text-sm">{form.errors.image}</p>
                                    ) : null}
                                </div>
                            </div>
                        </div>

                        <div className="grid gap-5 sm:grid-cols-2">
                            <div className="space-y-2 sm:col-span-2">
                                <Label htmlFor="full_name">{labels.fullName}</Label>
                                <Input
                                    id="full_name"
                                    value={form.data.full_name}
                                    onChange={(e) => form.setData('full_name', e.target.value)}
                                    autoComplete="name"
                                    aria-invalid={Boolean(form.errors.full_name)}
                                    className={cn(form.errors.full_name && 'border-destructive')}
                                />
                                {form.errors.full_name ? (
                                    <p className="text-destructive text-sm">{form.errors.full_name}</p>
                                ) : null}
                            </div>
                            <div className="space-y-2">
                                <Label htmlFor="national_card_number">{labels.nationalCardNumber}</Label>
                                <Input
                                    id="national_card_number"
                                    value={form.data.national_card_number}
                                    onChange={(e) =>
                                        form.setData('national_card_number', e.target.value)
                                    }
                                    aria-invalid={Boolean(form.errors.national_card_number)}
                                    className={cn(
                                        form.errors.national_card_number && 'border-destructive',
                                    )}
                                />
                                {form.errors.national_card_number ? (
                                    <p className="text-destructive text-sm">
                                        {form.errors.national_card_number}
                                    </p>
                                ) : null}
                            </div>
                        </div>
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>{labels.sectionContact}</CardTitle>
                        <CardDescription>{labels.sectionContactHint}</CardDescription>
                    </CardHeader>
                    <CardContent className="space-y-5">
                        <div className="space-y-2">
                            <Label htmlFor="supply_zone">{labels.supplyZone}</Label>
                            <Input
                                id="supply_zone"
                                value={form.data.supply_zone}
                                onChange={(e) => form.setData('supply_zone', e.target.value)}
                                aria-invalid={Boolean(form.errors.supply_zone)}
                                className={cn(form.errors.supply_zone && 'border-destructive')}
                            />
                            {form.errors.supply_zone ? (
                                <p className="text-destructive text-sm">{form.errors.supply_zone}</p>
                            ) : null}
                        </div>
                        <div className="space-y-2">
                            <Label htmlFor="address">{labels.address}</Label>
                            <textarea
                                id="address"
                                name="address"
                                value={form.data.address}
                                onChange={(e) => form.setData('address', e.target.value)}
                                aria-invalid={Boolean(form.errors.address)}
                                className={textareaClassName}
                            />
                            {form.errors.address ? (
                                <p className="text-destructive text-sm">{form.errors.address}</p>
                            ) : null}
                        </div>
                        <div className="space-y-2">
                            <Label htmlFor="contact_number">{labels.contactNumber}</Label>
                            <Input
                                id="contact_number"
                                value={form.data.contact_number}
                                onChange={(e) => form.setData('contact_number', e.target.value)}
                                aria-invalid={Boolean(form.errors.contact_number)}
                                className={cn(form.errors.contact_number && 'border-destructive')}
                            />
                            {form.errors.contact_number ? (
                                <p className="text-destructive text-sm">{form.errors.contact_number}</p>
                            ) : null}
                        </div>
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>{labels.sectionDocuments}</CardTitle>
                        <CardDescription>{labels.sectionDocumentsHint}</CardDescription>
                    </CardHeader>
                    <CardContent className="space-y-5">
                        <FileField
                            id="national_card"
                            label={labels.nationalCardImage}
                            hint={labels.nationalCardHint}
                            accept="image/jpeg,image/png,image/webp,.jpg,.jpeg,.png,.webp"
                            error={form.errors.national_card}
                            currentUrl={customer?.national_card_url}
                            currentLabel={labels.viewCurrentFile}
                            onChange={(e) => form.setData('national_card', e.target.files?.[0] ?? null)}
                        />
                        <FileField
                            id="car_image"
                            label={labels.carImage}
                            hint={labels.carImageHint}
                            accept="image/jpeg,image/png,image/webp,.jpg,.jpeg,.png,.webp"
                            error={form.errors.car_image}
                            currentUrl={customer?.car_image_url}
                            currentLabel={labels.viewCurrentFile}
                            onChange={(e) => form.setData('car_image', e.target.files?.[0] ?? null)}
                        />
                    </CardContent>
                </Card>

                <Card>
                    <CardContent className="flex flex-col gap-4 pt-6 sm:flex-row sm:items-center sm:justify-between">
                        <div className="flex items-center gap-3">
                            <Switch
                                id="is_active"
                                checked={form.data.is_active}
                                onCheckedChange={(checked) => form.setData('is_active', checked)}
                            />
                            <div className="space-y-0.5">
                                <Label htmlFor="is_active">{labels.isActive}</Label>
                                <p className="text-muted-foreground text-xs">{labels.isActiveHint}</p>
                            </div>
                        </div>
                        <Button type="submit" disabled={form.processing} className="min-w-[10rem]">
                            {form.processing ? (
                                <>
                                    <Spinner className="size-4" />
                                    {submittingLabel}
                                </>
                            ) : (
                                submitLabel
                            )}
                        </Button>
                    </CardContent>
                </Card>
            </form>
        </>
    );
}
