import { useForm } from '@inertiajs/react';
import { useEffect, useMemo, useRef } from 'react';
import UserController from '@/actions/App/Http/Controllers/UserController';
import FormLabel from '@/components/form-label';
import InputError from '@/components/input-error';
import PasswordInput from '@/components/password-input';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
    Sheet,
    SheetContent,
    SheetDescription,
    SheetFooter,
    SheetHeader,
    SheetTitle,
} from '@/components/ui/sheet';
import { Spinner } from '@/components/ui/spinner';
import { cn } from '@/lib/utils';
import type { UserDetail, UserFormPayload, UserRole } from '@/types';
import { formatUserName } from './helpers';
import { RoleSelector } from './role-selector';

const emptyForm: UserFormPayload = {
    first_name: '',
    last_name: '',
    ci_number: '',
    ci_complement: '',
    phone: '',
    email: '',
    organization: '',
    role: '',
    password: '',
    password_confirmation: '',
};

type Props = {
    mode: 'create' | 'edit';
    open: boolean;
    user?: UserDetail | null;
    roles?: UserRole[];
    organizationSuggestions?: string[];
    onOpenChange: (open: boolean) => void;
};

export function UserFormSheet({
    mode,
    open,
    user,
    roles,
    organizationSuggestions = [],
    onOpenChange,
}: Props) {
    const defaults = useMemo<UserFormPayload>(() => {
        if (!user) {
            return { ...emptyForm };
        }

        return {
            first_name: user.first_name ?? '',
            last_name: user.last_name ?? '',
            ci_number: user.ci_number ?? '',
            ci_complement: user.ci_complement ?? '',
            phone: user.phone ?? '',
            email: user.email ?? '',
            organization: user.organization ?? '',
            role: user.role ?? user.roles?.[0]?.name ?? '',
            password: '',
            password_confirmation: '',
        };
    }, [user]);
    const previousOpen = useRef(open);
    const previousDefaults = useRef(defaults);

    const form = useForm<UserFormPayload>(defaults);

    useEffect(() => {
        if (!open) {
            previousOpen.current = false;

            return;
        }

        if (previousOpen.current && previousDefaults.current === defaults) {
            return;
        }

        form.setDefaults(defaults);
        form.reset();
        form.clearErrors();

        previousOpen.current = true;
        previousDefaults.current = defaults;
    }, [defaults, form, open]);

    const isCreate = mode === 'create';

    const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
        event.preventDefault();

        const action = isCreate
            ? UserController.store()
            : UserController.update(user?.id);

        form.submit(action, {
            preserveScroll: true,
            onSuccess: () => {
                onOpenChange(false);
                form.reset();
                form.clearErrors();
            },
        });
    };

    return (
        <Sheet open={open} onOpenChange={onOpenChange}>
            <SheetContent side="right" className="w-full p-0 sm:max-w-2xl">
                <SheetHeader className="border-b pb-5">
                    <SheetTitle>
                        {isCreate
                            ? 'Nuevo usuario'
                            : `Editar a ${formatUserName(user ?? {})}`}
                    </SheetTitle>
                    <SheetDescription>
                        {isCreate
                            ? 'Registra una cuenta nueva y asigna un rol operativo.'
                            : 'Actualiza los datos personales y el rol de acceso del usuario.'}
                    </SheetDescription>
                </SheetHeader>

                <form
                    onSubmit={handleSubmit}
                    className="flex min-h-0 flex-1 flex-col gap-6 overflow-y-auto p-4 md:p-6"
                >
                    <div className="grid gap-4 md:grid-cols-2">
                        <div className="grid gap-2">
                            <FormLabel htmlFor="first_name" required>
                                Nombres
                            </FormLabel>
                            <Input
                                id="first_name"
                                value={form.data.first_name}
                                aria-invalid={
                                    form.errors.first_name ? true : undefined
                                }
                                onChange={(event) =>
                                    form.setData(
                                        'first_name',
                                        event.target.value,
                                    )
                                }
                                placeholder="Nombres"
                            />
                            <InputError message={form.errors.first_name} />
                        </div>
                        <div className="grid gap-2">
                            <FormLabel htmlFor="last_name" required>
                                Apellidos
                            </FormLabel>
                            <Input
                                id="last_name"
                                value={form.data.last_name}
                                aria-invalid={
                                    form.errors.last_name ? true : undefined
                                }
                                onChange={(event) =>
                                    form.setData(
                                        'last_name',
                                        event.target.value,
                                    )
                                }
                                placeholder="Apellidos"
                            />
                            <InputError message={form.errors.last_name} />
                        </div>
                    </div>

                    <div className="grid gap-4 md:grid-cols-[1fr_140px]">
                        <div className="grid gap-2">
                            <FormLabel htmlFor="ci_number" required>
                                CI
                            </FormLabel>
                            <Input
                                id="ci_number"
                                value={form.data.ci_number}
                                aria-invalid={
                                    form.errors.ci_number ? true : undefined
                                }
                                onChange={(event) =>
                                    form.setData(
                                        'ci_number',
                                        event.target.value,
                                    )
                                }
                                placeholder="Numero de cedula"
                            />
                            <InputError message={form.errors.ci_number} />
                        </div>
                        <div className="grid gap-2">
                            <FormLabel htmlFor="ci_complement">
                                Complemento
                            </FormLabel>
                            <Input
                                id="ci_complement"
                                value={form.data.ci_complement}
                                aria-invalid={
                                    form.errors.ci_complement ? true : undefined
                                }
                                onChange={(event) =>
                                    form.setData(
                                        'ci_complement',
                                        event.target.value.toUpperCase(),
                                    )
                                }
                                placeholder="A, 1, etc."
                            />
                            <InputError message={form.errors.ci_complement} />
                        </div>
                    </div>

                    <div className="grid gap-2">
                        <FormLabel htmlFor="phone">Telefono</FormLabel>
                        <Input
                            id="phone"
                            value={form.data.phone}
                            aria-invalid={form.errors.phone ? true : undefined}
                            onChange={(event) =>
                                form.setData('phone', event.target.value)
                            }
                            placeholder="Numero de contacto"
                        />
                        <InputError message={form.errors.phone} />
                    </div>

                    <div className="grid gap-2">
                        <FormLabel htmlFor="email" required>
                            Correo electronico
                        </FormLabel>
                        <Input
                            id="email"
                            type="email"
                            value={form.data.email}
                            aria-invalid={form.errors.email ? true : undefined}
                            onChange={(event) =>
                                form.setData('email', event.target.value)
                            }
                            placeholder="usuario@institucion.bo"
                        />
                        <InputError message={form.errors.email} />
                    </div>

                    <div className="grid gap-2">
                        <FormLabel htmlFor="organization">
                            Organizacion
                        </FormLabel>
                        <Input
                            id="organization"
                            list="user-organization-suggestions"
                            value={form.data.organization}
                            aria-invalid={
                                form.errors.organization ? true : undefined
                            }
                            onChange={(event) =>
                                form.setData('organization', event.target.value)
                            }
                            placeholder="UATF, GAMP u otra entidad"
                        />
                        {organizationSuggestions.length > 0 && (
                            <datalist id="user-organization-suggestions">
                                {organizationSuggestions.map((organization) => (
                                    <option
                                        key={organization}
                                        value={organization}
                                    />
                                ))}
                            </datalist>
                        )}
                        <InputError message={form.errors.organization} />
                    </div>

                    <RoleSelector
                        name="role"
                        value={form.data.role}
                        roles={roles}
                        error={form.errors.role}
                        onChange={(value) => form.setData('role', value)}
                    />

                    {isCreate && (
                        <div className="grid gap-4 md:grid-cols-2">
                            <div className="grid gap-2">
                                <FormLabel htmlFor="password" required>
                                    Contrasena
                                </FormLabel>
                                <PasswordInput
                                    id="password"
                                    value={form.data.password}
                                    aria-invalid={
                                        form.errors.password ? true : undefined
                                    }
                                    onChange={(event) =>
                                        form.setData(
                                            'password',
                                            event.target.value,
                                        )
                                    }
                                    placeholder="Minimo 8 caracteres"
                                />
                                <InputError message={form.errors.password} />
                            </div>
                            <div className="grid gap-2">
                                <FormLabel
                                    htmlFor="password_confirmation"
                                    required
                                >
                                    Confirmar contrasena
                                </FormLabel>
                                <PasswordInput
                                    id="password_confirmation"
                                    value={form.data.password_confirmation}
                                    aria-invalid={
                                        form.errors.password_confirmation
                                            ? true
                                            : undefined
                                    }
                                    onChange={(event) =>
                                        form.setData(
                                            'password_confirmation',
                                            event.target.value,
                                        )
                                    }
                                    placeholder="Repite la contrasena"
                                />
                                <InputError
                                    message={form.errors.password_confirmation}
                                />
                            </div>
                        </div>
                    )}

                    <SheetFooter className={cn('border-t px-0 pt-5')}>
                        <div className="flex w-full flex-col-reverse gap-2 sm:flex-row sm:justify-end">
                            <Button
                                type="button"
                                variant="outline"
                                onClick={() => onOpenChange(false)}
                            >
                                Cancelar
                            </Button>
                            <Button type="submit" disabled={form.processing}>
                                {form.processing && <Spinner />}
                                {isCreate
                                    ? 'Guardar usuario'
                                    : 'Guardar cambios'}
                            </Button>
                        </div>
                    </SheetFooter>
                </form>
            </SheetContent>
        </Sheet>
    );
}
