import {useEffect, useRef} from '@wordpress/element';
import {urlSearchParams} from "../../../../../../helpers";
import {ALL_SETTINGS_ERRORS_DATA_KEY, getInitialData} from "../../../../../helpers";
import {handleError} from "../../../../../helpers/notifications";

export default function useSettingsErrorsState({settings, errors, title, validateField, isDataFetched}) {
    const currentPageInfo = useRef();
    // Settings ref
    const settingsRef = useRef(getInitialData(settings));

    useEffect(() => {
        getCurrentPageInfo();
    }, []);

    useEffect(() => {
        checkErrors(errors);
    }, [errors]);

    useEffect(() => {
        // Validate fields on unmount
        return () => {
            if (isDataFetched) {
                checkErrorsOnUnmount(title);
            }
        }
    }, [isDataFetched]);

    useEffect(() => {
        if (isDataFetched) {
            // Settings ref update
            settingsRef.current = getInitialData(settings);
        }
    }, [isDataFetched, settings]);

    /**
     * Get current page info
     */
    const getCurrentPageInfo = () => {
        const searchParams = new URLSearchParams(window.location.search);
        const keys = ['menu', 'tab', 'utility', 'action'];
        // Current page params
        const params = keys.reduce((acc, key) => {
            const value = searchParams.get(key);
            if (value) {
                acc[key] = value;
            }
            return acc;
        }, {});

        currentPageInfo.current = urlSearchParams(params, '');
    }

    /**
     * Update errors' storage
     *
     * @param {string[]} fieldsWithErrors Fields keys that has error
     */
    const updateErrorsStorage = (fieldsWithErrors) => {
        // Get the storage of errors
        const errorsStorage = JSON.parse(sessionStorage.getItem(ALL_SETTINGS_ERRORS_DATA_KEY) || '{}');
        if (fieldsWithErrors.length > 0) {
            // Set new state of errors
            errorsStorage[currentPageInfo.current] = {
                fields: fieldsWithErrors,
                title: title,
            };
        } else {
            // Clear current page errors storage
            if (currentPageInfo.current in errorsStorage) {
                delete errorsStorage[currentPageInfo.current];
            } else {
                // Nothing to do, no changes detected
                return;
            }
        }
        // Update the errors' storage
        sessionStorage.setItem(ALL_SETTINGS_ERRORS_DATA_KEY, JSON.stringify(errorsStorage));
    }

    /**
     * Tab errors
     *
     * @param {object} fieldsErrors Tab fields errors
     */
    const checkErrors = (fieldsErrors) => {
        try {
            // Skip if page info isn't defined
            if (!currentPageInfo.current) {
                return;
            }
            // Fields which has error
            const fieldsHasError = [];
            // Tabs fields keys
            const fieldKeys = Object.keys(fieldsErrors);
            // Check which field has error
            for (const fieldKey of fieldKeys) {
                // Check if it has error
                if (fieldsErrors[fieldKey][0]) {
                    fieldsHasError.push(fieldKey);
                }
            }
            // Update the errors' storage
            updateErrorsStorage(fieldsHasError);
        } catch (e) {
            handleError(e);
        }
    }

    /**
     * Check errors on unmounting
     *
     * @return {boolean}
     */
    const checkErrorsOnUnmount = () => {
        try {
            // Skip if page info isn't defined
            if (!currentPageInfo.current || typeof validateField !== 'function') {
                return;
            }
            // Fields which has error
            const fieldsHasError = [];
            // Check which field has error
            for (const key in settingsRef.current) {
                if (!validateField(key, settingsRef.current[key])) {
                    fieldsHasError.push(key);
                }
            }
            // Update the errors' storage
            updateErrorsStorage(fieldsHasError);
        } catch (e) {
            handleError(e);
        }
    }
}