'use client';

import { ReactElement, ReactNode, useEffect } from 'react';
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form';

type FromConfig = {
    defaultValues?: Record<string, any>;
    resolver?: any;
    formClassNames?: string;
    resetAfterSubmit?: boolean;
};

type FormProps = {
    children: ReactElement | ReactNode;
    submitHandler: SubmitHandler<any>;
    externalErrors?: Record<string, string | string[]>; // Inertia errors
    id?: string;
} & FromConfig;

const Form = ({ children, submitHandler, defaultValues, resolver, formClassNames = '', resetAfterSubmit = false, externalErrors, id }: FormProps) => {
    const formConfig: FromConfig = {};
    if (!!defaultValues) formConfig['defaultValues'] = defaultValues;
    if (!!resolver) formConfig['resolver'] = resolver;

    const methods = useForm(formConfig);
    const { handleSubmit, reset, setError, setFocus, clearErrors, formState: { errors } } = methods;

    const onSubmit = async (data: any) => {
        try {
            clearErrors(); // clear previous server errors before new submit
            await submitHandler(data);
            if (resetAfterSubmit) {
                methods.reset();
            }
        } catch (err: any) {
            console.log(err.message);
        }
    };

    useEffect(() => {
        // Avoid resetting while there are external validation errors; that would clear them
        const hasExternalErrors = externalErrors && Object.keys(externalErrors).length > 0;
        if (hasExternalErrors) return;
        reset(defaultValues);
    }, [defaultValues, reset, methods, externalErrors]);

    // Apply external (Inertia) validation errors directly
    useEffect(() => {
        if (!externalErrors) return;
        const keys = Object.keys(externalErrors);
        if (!keys.length) return;
        keys.forEach((field) => {
            const raw = externalErrors[field];
            const msg = Array.isArray(raw) ? raw[0] : raw;
            if (msg) setError(field as any, { type: 'server', message: msg });
        });
        // Focus first error field
        setTimeout(() => setFocus(keys[0] as any), 0);
    }, [externalErrors, setError, setFocus]);

    // Auto-scroll to first error field when validation fails
    useEffect(() => {
        const errorKeys = Object.keys(errors);
        if (errorKeys.length === 0) return;

        const firstErrorField = errorKeys[0];
        
        // Try to find the input element by name or id
        const element = document.querySelector(`[name="${firstErrorField}"]`) || 
                       document.getElementById(firstErrorField) ||
                       document.getElementById(`${firstErrorField}-error`);
        
        if (element) {
            element.scrollIntoView({ behavior: 'smooth', block: 'center' });
            // Focus the field if it's an input
            if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement) {
                setTimeout(() => (element as HTMLElement).focus(), 100);
            }
        }
    }, [errors]);

    return (
        <FormProvider {...methods}>
            <form id={id} className={formClassNames} onSubmit={handleSubmit(onSubmit)}>
                {children}
            </form>
        </FormProvider>
    );
};

export default Form;
