import { useForm } from '@inertiajs/react';
import { useEffect, useMemo, useState } from 'react';
import { toast } from 'sonner';
import { ConfirmActionDialog } from '@/components/confirm-action-dialog';
import { DesignationSelect } from '@/components/employees/designation-select';
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 { buildTemporaryEmployeeSchema } 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.employee]
 * @param {Array<{id: number, name: string, is_active?: boolean}>} [props.designations]
 * @param {string} props.submitUrl
 * @param {'post' | 'put'} props.submitMethod
 * @param {string} props.submitLabel
 * @param {string} props.submittingLabel
 * @param {() => void} [props.onSuccess]
 */
export function TemporaryEmployeeForm({
    mode,
    labels,
    employee,
    designations = [],
    submitUrl,
    submitMethod,
    submitLabel,
    submittingLabel,
    onSuccess,
}) {
    const { t } = useLanguage();
    const p = t.employeesTemporaryPage;
    const a = t.appActions;
    const getInitials = useInitials();
    const isEdit = mode === 'edit';
    const [confirmOpen, setConfirmOpen] = useState(false);

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

    const form = useForm({
        full_name: employee?.full_name ?? '',
        father_name: employee?.father_name ?? '',
        national_card_number: employee?.national_card_number ?? '',
        address: employee?.address ?? '',
        contact_number: employee?.contact_number ?? '',
        designation_id: employee?.designation_id ?? '',
        is_active: employee?.is_active ?? true,
        image: null,
        health_card: null,
    });

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

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

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

    const docAccept =
        'image/jpeg,image/png,image/webp,.jpg,.jpeg,.png,.webp,application/pdf,.pdf';

    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(employee?.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.put(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.image}</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="father_name">{labels.fatherName}</Label>
                                <Input
                                    id="father_name"
                                    value={form.data.father_name}
                                    onChange={(e) => form.setData('father_name', e.target.value)}
                                    aria-invalid={Boolean(form.errors.father_name)}
                                    className={cn(form.errors.father_name && 'border-destructive')}
                                />
                                {form.errors.father_name ? (
                                    <p className="text-destructive text-sm">{form.errors.father_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 className="sm:col-span-2">
                                <DesignationSelect
                                    designations={designations}
                                    value={form.data.designation_id}
                                    onValueChange={(value) => {
                                        form.setData('designation_id', Number(value));
                                        if (form.errors.designation_id) {
                                            form.clearErrors('designation_id');
                                        }
                                    }}
                                    labels={labels}
                                    error={form.errors.designation_id}
                                />
                            </div>
                        </div>
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>{labels.sectionContact}</CardTitle>
                        <CardDescription>{labels.sectionContactHint}</CardDescription>
                    </CardHeader>
                    <CardContent className="grid gap-5">
                        <div className="space-y-2">
                            <Label htmlFor="contact_number">{labels.contactNumber}</Label>
                            <Input
                                id="contact_number"
                                type="tel"
                                value={form.data.contact_number}
                                onChange={(e) => form.setData('contact_number', e.target.value)}
                                autoComplete="tel"
                                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>
                        <div className="space-y-2">
                            <Label htmlFor="address">{labels.address}</Label>
                            <textarea
                                id="address"
                                rows={4}
                                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>
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>{labels.sectionStatus}</CardTitle>
                        <CardDescription>{labels.sectionStatusHint}</CardDescription>
                    </CardHeader>
                    <CardContent>
                        <div className="flex items-center justify-between gap-4 rounded-lg border border-border px-4 py-3">
                            <div className="space-y-0.5">
                                <Label htmlFor="is_active">{labels.isActive}</Label>
                                <p className="text-muted-foreground text-xs">{labels.isActiveHint}</p>
                            </div>
                            <Switch
                                id="is_active"
                                checked={form.data.is_active}
                                onCheckedChange={(checked) => form.setData('is_active', checked)}
                            />
                        </div>
                        {form.errors.is_active ? (
                            <p className="text-destructive mt-2 text-sm">{form.errors.is_active}</p>
                        ) : null}
                    </CardContent>
                </Card>

                <Card>
                    <CardHeader>
                        <CardTitle>{labels.sectionDocuments}</CardTitle>
                        <CardDescription>
                            {isEdit ? labels.sectionDocumentsEditHint : labels.sectionDocumentsHint}
                        </CardDescription>
                    </CardHeader>
                    <CardContent>
                        <FileField
                            id="health_card"
                            label={labels.healthCard}
                            hint={labels.documentHint}
                            accept={docAccept}
                            error={form.errors.health_card}
                            currentUrl={employee?.health_card_url}
                            currentLabel={labels.viewCurrentFile}
                            onChange={(e) =>
                                form.setData('health_card', e.target.files?.[0] ?? null)
                            }
                        />
                    </CardContent>
                </Card>

                <div className="flex flex-wrap items-center gap-3 pb-4">
                    <Button type="submit" disabled={form.processing} className="gap-2">
                        {form.processing ? <Spinner /> : null}
                        {form.processing ? submittingLabel : submitLabel}
                    </Button>
                </div>
            </form>
        </>
    );
}
