'use client';

import { useState, useEffect } from 'react';

interface IValidationRule {
    check: (value: string, formData: IFormData) => boolean;
    message: string
}

export interface IValidationSchema {
    [key: string]: IValidationRule[]
}

export interface IFormData {
    [key: string]: FormFieldValue;
}

type FormFieldValue = any;

export interface IFormErrors {
    [key: string]: FormFieldValue;
}

export const useForm = <T extends IFormData>(onSubmit: (formData: T) => Promise<null | string | undefined | void>, validationSchema: IValidationSchema, initValue = {} as T) => {
    const [formData, setFormData] = useState<T>(initValue);
    const [errors, setErrors] = useState<IFormErrors>({});
    const [isProgress, setIsProgress] = useState(false);
    const [isValid, setIsValid] = useState({});
    const [showErrors, setShowErrors] = useState(false);
    const [formError, setFormError] = useState<null | string>(null);

    const handleChangeField = (name: keyof T) => (newValue: FormFieldValue) => {
        const newData = {...formData};
        (newData as any)[name] = newValue;
        setFormData(newData);
    }

    const handleSubmit = (e?: any) => {
        if (e && 'preventDefault' in e) {e.preventDefault()}
        setShowErrors(true)
        if(isValid) {
            setIsProgress(true)
            const call = async () => {
                const res = await onSubmit(formData);
                setFormError(res || null);
                setIsProgress(false)
            }
            call();
        }
    }

    const handleReset = () => {
        setFormData(JSON.parse(JSON.stringify(initValue)))
        setShowErrors(false);
    }

    useEffect(() => {
        const newErrors: IFormErrors = {};

        Object.keys(validationSchema).forEach((key) => {
            validationSchema[key].forEach((rule) => {
                if(newErrors[key]) {
                    return;
                }
                if(!rule.check(formData[key], formData)) {
                    newErrors[key] = rule.message;
                }
            })
        })

        setErrors(newErrors);
        setIsValid(Object.values(newErrors).every(el => el == undefined))
    }, [formData, validationSchema])

    return {
        handleChangeField,
        formData,
        handleSubmit,
        handleReset,
        errors,
        isValid,
        showErrors,
        formError,
        isProgress
    }
}