import { useCallback, useReducer } from '@lynx-js/react';
import { ZodObject, ZodTransformer } from 'zod';
import { reset, setError, setIsSubmitting, setTouched, setValue, } from '../reducers/formActions.js';
import { formReducer, } from '../reducers/formReducer.jsx';
export const useForm = (onSubmit, initialValues, validate, schema) => {
    const [state, dispatch] = useReducer((formReducer), {
        values: initialValues || {},
        errors: {},
        touched: {},
        isSubmitting: false,
    });
    const validateField = useCallback((field, value) => {
        if (schema) {
            const result = schema.safeParse(value !== undefined
                ? { ...state.values, [field]: value }
                : state.values);
            console.log(result.error?.format());
            setFormError(field, (result.error?.format())[field]?._errors[0] || '');
        }
        else if (validate) {
            const errors = validate({ ...state.values, [field]: value });
            setFormError(field, errors[field] || '');
        }
    }, [validate, schema, setFormError]);
    const handleInput = useCallback((field) => (e) => {
        const value = e.detail.value;
        setFormValue(field, value);
        validateField(field, value);
    }, [state.values, validateField]);
    const handleBlur = useCallback((field) => () => {
        setTouched(dispatch, field, true);
        validateField(field);
    }, [state.values, validateField]);
    const handleSubmit = useCallback(() => {
        if (schema) {
            const errors = schema.safeParse(state.values).error?.format();
            if (errors) {
                for (const [field, value] of Object.entries(errors)) {
                    const parsedValue = value;
                    if (parsedValue?._errors)
                        setFormError(field, parsedValue?._errors[0]);
                }
                return;
            }
        }
        else if (validate) {
            const errors = validate(state.values);
            if (Object.keys(errors).length > 0) {
                Object.keys(errors).forEach((field) => {
                    setFormError(field, errors[field] || '');
                });
                return;
            }
        }
        setIsSubmitting(dispatch, true);
        Promise.resolve(onSubmit(state.values, { setValue: setFormValue, setError: setFormError })).finally(() => setIsSubmitting(dispatch, false));
    }, [validate, schema, state.values, onSubmit, setFormError, setFormValue]);
    const resetForm = useCallback(() => reset(dispatch, initialValues), [initialValues]);
    function setFormValue(field, value) {
        setValue(dispatch, field, value);
    }
    function setFormError(field, error) {
        setError(dispatch, field, error);
    }
    return {
        values: state.values,
        errors: state.errors,
        touched: state.touched,
        handleInput,
        handleBlur,
        handleSubmit,
        resetForm,
        setValue: setFormValue,
        setError: setFormError,
        isSubmitting: state.isSubmitting,
    };
};
