/*
    Предрейсовые осмотры - мобильное приложение
    Хук для взаимодействия с сервером приложений
*/

//---------------------
//Подключение библиотек
//---------------------

const React = require('react');
const { useAppLocalDbContext } = require('../components/layout/AppLocalDbProvider'); //Контекст локальной БД

//---------
//Константы
//---------

const RESP_STATUS_OK = 'OK';
const RESP_STATUS_ERR = 'ERR';

const ERR_APPSERVER = 'Ошибка сервера приложений';
const ERR_NETWORK = 'Ошибка соединения с сервером';
const ERR_UNEXPECTED = 'Неожиданный ответ сервера';
const ERR_ABORTED = 'Запрос прерван принудительно';

//-----------------------
//Вспомогательные функции
//-----------------------

//Создание объекта ошибки ответа
const makeRespErr = ({ message }) => ({
    status: RESP_STATUS_ERR,
    message
});

//Проверка является ли ответ ошибкой
const isRespErr = resp => resp && resp.status === RESP_STATUS_ERR;

//Получение сообщения об ошибке из ответа
const getRespErrMessage = resp => (isRespErr(resp) && resp.message ? resp.message : '');

//-----------
//Тело модуля
//-----------

//Хук для взаимодействия с сервером приложений
function useAppServer() {
    const { getSetting } = useAppLocalDbContext();
    const abortControllerRef = React.useRef(null);

    //Принудительная отмена активного запроса
    const abort = React.useCallback(() => {
        if (abortControllerRef.current) {
            abortControllerRef.current.abort();
        }
    }, []);

    //Выполнение произвольного действия на сервере
    const executeAction = React.useCallback(
        async ({ path = '', method = 'POST', payload = null } = {}) => {
            let baseURL = '';
            try {
                baseURL = (await getSetting('app_server_url')) || '';
            } catch (e) {
                console.warn('Не удалось прочитать настройки сервера:', e);
            }

            if (!baseURL) {
                return makeRespErr({
                    message: 'Адрес сервера не настроен. Пожалуйста, настройте сервер в настройках приложения.'
                });
            }

            const normalizedBaseURL = baseURL.endsWith('/') ? baseURL.slice(0, -1) : baseURL;
            const normalizedPath = path.startsWith('/') ? path : `/${path}`;
            const url = `${normalizedBaseURL}${normalizedPath}`;

            const abortController = new AbortController();
            abortControllerRef.current = abortController;

            let response = null;
            let responseJSON = null;

            try {
                response = await fetch(url, {
                    method,
                    headers: {
                        'content-type': 'application/json'
                    },
                    body: payload ? JSON.stringify(payload) : null,
                    signal: abortController.signal
                });
            } catch (e) {
                if (abortController.signal.aborted === true) {
                    return makeRespErr({ message: ERR_ABORTED });
                }
                return makeRespErr({
                    message: `${ERR_NETWORK}: ${e.message || 'неопределённая ошибка'}`
                });
            } finally {
                abortControllerRef.current = null;
            }

            if (!response.ok) {
                return makeRespErr({
                    message: `${ERR_APPSERVER}: ${response.status} ${response.statusText || ''}`
                });
            }

            try {
                responseJSON = await response.json();
            } catch (e) {
                return makeRespErr({ message: ERR_UNEXPECTED });
            }

            if (!responseJSON || !responseJSON.status) {
                return makeRespErr({ message: ERR_UNEXPECTED });
            }

            return responseJSON;
        },
        [getSetting]
    );

    //Автоматическая отмена при размонтировании хука
    React.useEffect(
        () => () => {
            abort();
        },
        [abort]
    );

    return {
        executeAction,
        abort,
        isRespErr,
        getRespErrMessage,
        RESP_STATUS_OK,
        RESP_STATUS_ERR
    };
}

//----------------
//Интерфейс модуля
//----------------

module.exports = useAppServer;
