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

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

const React = require('react'); //React и хуки
const { ScrollView, View, KeyboardAvoidingView, Platform } = require('react-native'); //Базовые компоненты
const AdaptiveView = require('../components/common/AdaptiveView'); //Адаптивный контейнер
const AppText = require('../components/common/AppText'); //Общий текст
const AppInput = require('../components/common/AppInput'); //Поле ввода
const AppButton = require('../components/common/AppButton'); //Кнопка
const AppSwitch = require('../components/common/AppSwitch'); //Переключатель
const PasswordInput = require('../components/common/PasswordInput'); //Поле пароля
const AppHeader = require('../components/layout/AppHeader'); //Заголовок
const AppLogo = require('../components/common/AppLogo'); //Логотип
const SideMenu = require('../components/menu/SideMenu'); //Боковое меню
const LoadingOverlay = require('../components/common/LoadingOverlay'); //Оверлей загрузки
const OrganizationSelectDialog = require('../components/auth/OrganizationSelectDialog'); //Диалог выбора организации
const { useAppMessagingContext } = require('../components/layout/AppMessagingProvider'); //Контекст сообщений
const { useAppModeContext } = require('../components/layout/AppModeProvider'); //Контекст режима
const { useAppNavigationContext } = require('../components/layout/AppNavigationProvider'); //Контекст навигации
const { useHardwareScannerContext } = require('../components/layout/HardwareScannerProvider'); //Встроенный сканер
const { useAppLocalDbContext } = require('../components/layout/AppLocalDbProvider'); //Контекст локальной БД
const { useAppAuthContext } = require('../components/layout/AppAuthProvider'); //Контекст авторизации
const { getAppInfo } = require('../utils/appInfo'); //Информация о приложении
const { isServerUrlFieldVisible } = require('../utils/loginFormUtils'); //Утилиты формы входа
const { parseScannedSegmentsForAuth } = require('../utils/authScannerUtils'); //Разбор данных сканера по Enter для экрана входа
const { getAllowedAuthFields } = require('../utils/authFormFieldsOrder'); //Порядок и доступность полей формы для сканера
const useScanInputHandler = require('../hooks/useScanInputHandler'); //Универсальный обработчик данных сканера для полей ввода
const { normalizeServerUrl, validateServerUrl } = require('../utils/validation'); //Валидация
const { AUTH_SETTINGS_KEYS } = require('../config/authConfig'); //Конфиг авторизации
const { MENU_ITEM_ID_SETTINGS, MENU_ITEM_ID_ABOUT, MENU_ITEM_ID_LOGOUT, MENU_ITEM_ID_DIVIDER } = require('../config/menuItemIds'); //ID пунктов меню
const { getAuthFormStore, setAuthFormStore, clearAuthFormStore } = require('../utils/authFormStore'); //Хранилище формы входа
const {
    APP_ABOUT_TITLE,
    SIDE_MENU_TITLE,
    ORGANIZATION_SELECT_DIALOG_TITLE,
    MENU_ITEM_SETTINGS,
    MENU_ITEM_ABOUT,
    MENU_ITEM_LOGOUT,
    AUTH_SCREEN_TITLE,
    AUTH_BUTTON_LOGIN,
    AUTH_BUTTON_LOADING,
    AUTH_BUTTON_LOGOUT,
    AUTH_SERVER_CHANGE_CONFIRM_TITLE,
    AUTH_SERVER_CHANGE_CONFIRM_MESSAGE,
    AUTH_SERVER_CHANGE_CONFIRM_BUTTON,
    AUTH_SERVER_CHANGE_CANCEL_BUTTON,
    LOGOUT_CONFIRM_TITLE,
    LOGOUT_CONFIRM_MESSAGE
} = require('../config/messages'); //Сообщения
const { DIALOG_BUTTON_TYPE, DIALOG_CANCEL_BUTTON, getConfirmButtonOptions } = require('../config/dialogButtons'); //Кнопки диалогов
const { createLogoutHandler } = require('../utils/logoutFlow'); //Универсальный поток выхода
const { APP_COLORS } = require('../config/theme'); //Цветовая схема
const { noopCatch } = require('../utils/noop'); //Пустой обработчик для .catch()
const styles = require('../styles/screens/AuthScreen.styles'); //Стили экрана

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

//Экран аутентификации
function AuthScreen() {
    const { showError, showInfo } = useAppMessagingContext();
    const { APP_MODE, mode, setOnline, setNotConnected } = useAppModeContext();
    const { navigate, goBack, canGoBack, reset, setInitialScreen, screenParams, currentScreen, SCREENS } = useAppNavigationContext();
    const { getSetting, isDbReady } = useAppLocalDbContext();
    const {
        session,
        login,
        logout,
        selectCompany,
        isLoading,
        getSavedCredentials,
        getAuthSession,
        clearAuthSession,
        clearAuthFormData,
        getAndClearLastSavedServerUrlFromSettings
    } = useAppAuthContext();

    //Данные формы при монтировании — из хранилища (восстанавливаются при возврате с других экранов)
    const initialForm = getAuthFormStore();

    //Состояние меню
    const [menuVisible, setMenuVisible] = React.useState(false);

    //Состояние формы
    const [serverUrl, setServerUrl] = React.useState(initialForm.serverUrl || '');
    const [username, setUsername] = React.useState(initialForm.username || '');
    const [password, setPassword] = React.useState(initialForm.password || '');
    const [savePassword, setSavePassword] = React.useState(!!initialForm.savePassword);
    const [showPassword, setShowPassword] = React.useState(!!initialForm.showPassword);

    //Состояние отображения
    const [hideServerUrl, setHideServerUrl] = React.useState(false);
    const [savedServerUrlFromSettings, setSavedServerUrlFromSettings] = React.useState('');
    const [isSettingsLoaded, setIsSettingsLoaded] = React.useState(false);

    //Флаг для предотвращения повторной загрузки
    const initialLoadRef = React.useRef(false);

    //Флаг однократной подстановки сохранённого логина при готовности БД
    const savedLoginFilledRef = React.useRef(false);

    //Состояние выбора организации
    const [showOrgDialog, setShowOrgDialog] = React.useState(false);
    const [organizations, setOrganizations] = React.useState([]);
    const [pendingLoginData, setPendingLoginData] = React.useState(null);

    //Определяем режим открытия экрана (из меню или при старте)
    const isFromMenu = screenParams?.fromMenu === true;
    const fromMenuKey = screenParams?.fromMenuKey;

    //Ref актуальных значений формы (для записи в store при размонтировании)
    const formDataRef = React.useRef({
        serverUrl,
        username,
        password,
        savePassword,
        showPassword
    });

    //Ref полей ввода для перехода фокуса по Enter
    const serverInputRef = React.useRef(null);
    const loginInputRef = React.useRef(null);
    const passwordInputRef = React.useRef(null);

    //Поле ввода, на котором сейчас фокус (null — фокус сброшен)
    const focusedFieldRef = React.useRef(null);
    //После программного перехода фокуса сканером — следующее поле (для случая сброса фокуса устройством)
    const expectedNextTargetRef = React.useRef(null);

    const { registerHandler, unregisterHandler, SCREENS: scannerScreens } = useHardwareScannerContext();

    //Первый видимый элемент ввода на экране аутентификации (для подстановки при отсутствии фокуса)
    const firstVisibleAuthField = isServerUrlFieldVisible(hideServerUrl, savedServerUrlFromSettings) ? 'server' : 'login';

    //Список доступных полей для сканера (видимые и редактируемые)
    const allowedAuthFieldIds = React.useMemo(
        () =>
            getAllowedAuthFields({
                serverVisible: firstVisibleAuthField === 'server',
                serverEditable: !(isLoading || isFromMenu),
                loginEditable: !(isLoading || isFromMenu),
                passwordEditable: !isLoading
            }),
        [firstVisibleAuthField, isLoading, isFromMenu]
    );

    //Обработчики фокуса полей
    const handleServerFocus = React.useCallback(() => {
        focusedFieldRef.current = 'server';
    }, []);
    const handleLoginFocus = React.useCallback(() => {
        focusedFieldRef.current = 'login';
    }, []);
    const handlePasswordFocus = React.useCallback(() => {
        focusedFieldRef.current = 'password';
    }, []);
    const handleFieldBlur = React.useCallback(() => {
        focusedFieldRef.current = null;
    }, []);

    //Актуализация ref и store при изменении полей; при размонтировании — сохранение в store
    React.useEffect(() => {
        const next = { serverUrl, username, password, savePassword, showPassword };
        formDataRef.current = next;
        setAuthFormStore(next);
        return () => setAuthFormStore(formDataRef.current);
    }, [serverUrl, username, password, savePassword, showPassword]);

    //Обработчики полей формы: сразу пишем в store и ref, затем setState
    const handleServerUrlChange = React.useCallback(value => {
        formDataRef.current.serverUrl = value;
        setAuthFormStore({ serverUrl: value });
        setServerUrl(value);
    }, []);
    const handleUsernameChange = React.useCallback(value => {
        formDataRef.current.username = value;
        setAuthFormStore({ username: value });
        setUsername(value);
    }, []);
    const handlePasswordChange = React.useCallback(value => {
        formDataRef.current.password = value;
        setAuthFormStore({ password: value });
        setPassword(value);
    }, []);

    //Восстановление формы при возврате на экран логина
    React.useLayoutEffect(() => {
        if (!canGoBack) {
            return;
        }
        const storedForm = getAuthFormStore();
        const savedServerUrl = getAndClearLastSavedServerUrlFromSettings();
        const serverUrlVal = savedServerUrl || (storedForm.serverUrl != null ? String(storedForm.serverUrl) : '');
        const usernameVal = storedForm.username != null ? String(storedForm.username) : '';
        const passwordVal = storedForm.password != null ? String(storedForm.password) : '';
        const savePasswordVal = Boolean(storedForm.savePassword);
        const showPasswordVal = Boolean(storedForm.showPassword);
        setServerUrl(serverUrlVal);
        setUsername(usernameVal);
        setPassword(passwordVal);
        setSavePassword(savePasswordVal);
        setShowPassword(showPasswordVal);
        formDataRef.current = {
            serverUrl: serverUrlVal,
            username: usernameVal,
            password: passwordVal,
            savePassword: savePasswordVal,
            showPassword: showPasswordVal
        };
    }, [canGoBack, getAndClearLastSavedServerUrlFromSettings]);

    //При готовности БД один раз подставляем сохранённый логин в поле (только если в форме ещё нет логина)
    React.useEffect(() => {
        if (!isDbReady || savedLoginFilledRef.current) {
            return;
        }
        const storedForm = getAuthFormStore();
        if (storedForm.username && String(storedForm.username).trim()) {
            return;
        }
        savedLoginFilledRef.current = true;
        let cancelled = false;
        getSetting(AUTH_SETTINGS_KEYS.SAVED_LOGIN)
            .then(val => {
                if (!cancelled && val && typeof val === 'string' && val.trim()) {
                    setUsername(val.trim());
                }
            })
            .catch(noopCatch);
        return () => {
            cancelled = true;
        };
    }, [isDbReady, getSetting]);

    //Сброс формы и загрузка credentials при открытии из меню или в оффлайн
    React.useEffect(() => {
        const shouldLoadFromMenu = isFromMenu && isDbReady;
        const shouldLoadOffline = mode === APP_MODE.OFFLINE && isDbReady;
        if (!shouldLoadFromMenu && !shouldLoadOffline) {
            return;
        }

        const loadCredentialsFromMenu = async () => {
            try {
                if (isFromMenu) {
                    clearAuthFormData();
                    clearAuthFormStore();
                }

                //Загружаем сохранённый URL сервера
                const savedServerUrl = await getSetting(AUTH_SETTINGS_KEYS.SERVER_URL);
                const savedHideServerUrl = await getSetting(AUTH_SETTINGS_KEYS.HIDE_SERVER_URL);

                if (savedServerUrl) {
                    setServerUrl(savedServerUrl);
                }

                setSavedServerUrlFromSettings(savedServerUrl || '');
                setHideServerUrl(savedHideServerUrl === 'true' || savedHideServerUrl === true);

                //Загружаем сохранённые credentials
                const savedCredentials = await getSavedCredentials();

                if (savedCredentials && savedCredentials.login) {
                    //Логин подставляем всегда
                    setUsername(savedCredentials.login);

                    //Пароль подставляем только если он был сохранён
                    if (savedCredentials.savePasswordEnabled && savedCredentials.password) {
                        setPassword(savedCredentials.password);
                        setSavePassword(true);
                    } else {
                        //Сбрасываем пароль
                        setPassword('');
                        setSavePassword(false);
                    }
                } else {
                    //Нет сохранённых данных - сбрасываем форму
                    setUsername('');
                    setPassword('');
                    setSavePassword(false);
                }

                initialLoadRef.current = true;
            } catch (loadError) {
                setUsername('');
                setPassword('');
                setSavePassword(false);
            } finally {
                setIsSettingsLoaded(true);
            }
        };

        loadCredentialsFromMenu();
    }, [isFromMenu, isDbReady, fromMenuKey, mode, APP_MODE.OFFLINE, clearAuthFormData, getSetting, getSavedCredentials]);

    //Резервная загрузка только логина (если поле пустое) при открытии в оффлайн или из меню
    React.useEffect(() => {
        if (!isDbReady || username !== '' || (!isFromMenu && mode !== APP_MODE.OFFLINE)) {
            return;
        }

        const loadSavedLoginOnly = async () => {
            try {
                const savedLogin = await getSetting(AUTH_SETTINGS_KEYS.SAVED_LOGIN);
                if (savedLogin && typeof savedLogin === 'string') {
                    setUsername(savedLogin.trim());
                }
            } catch (_e) {}
        };

        loadSavedLoginOnly();
    }, [isDbReady, username, isFromMenu, mode, APP_MODE.OFFLINE, getSetting]);

    //Загрузка адреса сервера и настройки видимости поля (при возврате на экран форму не перезаписываем)
    React.useEffect(() => {
        if (!isDbReady || currentScreen !== SCREENS.AUTH) {
            return;
        }

        const loadServerAndVisibility = async () => {
            try {
                const savedUrl = await getSetting(AUTH_SETTINGS_KEYS.SERVER_URL);
                const savedHide = await getSetting(AUTH_SETTINGS_KEYS.HIDE_SERVER_URL);
                const trimmedUrl = savedUrl && String(savedUrl).trim() ? String(savedUrl).trim() : '';
                if (trimmedUrl && !canGoBack) {
                    setServerUrl(trimmedUrl);
                }
                setSavedServerUrlFromSettings(trimmedUrl);
                setHideServerUrl(savedHide === 'true' || savedHide === true);
            } catch (_e) {}
        };

        loadServerAndVisibility();
    }, [isDbReady, currentScreen, SCREENS.AUTH, canGoBack, getSetting]);

    //Загрузка настроек при готовности БД (только при первом открытии экрана; не перезаписываем форму, если в store уже есть введённые данные — возврат из настроек)
    React.useEffect(() => {
        if (!isDbReady || initialLoadRef.current || isFromMenu || canGoBack) {
            return;
        }
        const stored = getAuthFormStore();
        if ((stored.username && String(stored.username).trim()) || (stored.password && String(stored.password).length > 0)) {
            setIsSettingsLoaded(true);
            return;
        }

        initialLoadRef.current = true;

        const loadSettings = async () => {
            try {
                const savedServerUrl = await getSetting(AUTH_SETTINGS_KEYS.SERVER_URL);
                const savedHideServerUrl = await getSetting(AUTH_SETTINGS_KEYS.HIDE_SERVER_URL);

                const currentFormData = formDataRef.current;

                if (savedServerUrl && !currentFormData.serverUrl) {
                    setServerUrl(savedServerUrl);
                }

                setSavedServerUrlFromSettings(savedServerUrl || '');
                setHideServerUrl(savedHideServerUrl === 'true' || savedHideServerUrl === true);

                const savedCredentials = await getSavedCredentials();
                if (savedCredentials && savedCredentials.login) {
                    setUsername(savedCredentials.login);
                    if (savedCredentials.savePasswordEnabled && savedCredentials.password) {
                        setPassword(savedCredentials.password);
                        setSavePassword(true);
                    } else {
                        setPassword('');
                        setSavePassword(false);
                    }
                } else {
                    setUsername('');
                    setPassword('');
                    setSavePassword(false);
                }
            } catch (_loadError) {
            } finally {
                setIsSettingsLoaded(true);
            }
        };

        loadSettings();
    }, [isDbReady, isFromMenu, canGoBack, getSetting, getSavedCredentials]);

    //Валидация формы
    const validateForm = React.useCallback(() => {
        if (!hideServerUrl || !serverUrl) {
            const urlResult = validateServerUrl(serverUrl, { emptyMessage: 'Укажите адрес сервера' });
            if (urlResult !== true) {
                showError(urlResult);
                return false;
            }
        }

        if (!username.trim()) {
            showError('Укажите логин');
            return false;
        }

        if (!password.trim()) {
            showError('Укажите пароль');
            return false;
        }

        return true;
    }, [hideServerUrl, serverUrl, username, password, showError]);

    //Выполнение входа
    const performLogin = React.useCallback(
        async formOverride => {
            const data = formOverride != null ? formOverride : { serverUrl, username, password, savePassword };
            const s = (data.serverUrl != null ? String(data.serverUrl) : '').trim();
            const u = (data.username != null ? String(data.username) : '').trim();
            const p = (data.password != null ? String(data.password) : '').trim();
            const save = Boolean(data.savePassword);

            let idleTimeout = null;
            try {
                idleTimeout = await getSetting(AUTH_SETTINGS_KEYS.IDLE_TIMEOUT);
            } catch (_settingError) {}

            const result = await login({
                serverUrl: s,
                user: u,
                password: p,
                timeout: idleTimeout ? parseInt(idleTimeout, 10) : null,
                savePassword: save
            });

            if (!result.success) {
                showError(result.error || 'Ошибка входа');
                return;
            }

            if (result.needSelectCompany) {
                setOrganizations(result.organizations);
                setPendingLoginData({
                    serverUrl: result.serverUrl,
                    sessionId: result.sessionId,
                    user: result.user,
                    savePassword: result.savePassword,
                    loginCredentials: result.loginCredentials
                });
                setShowOrgDialog(true);
                return;
            }

            setOnline();
            clearAuthFormData();
            clearAuthFormStore();
            reset();
        },
        [login, serverUrl, username, password, savePassword, getSetting, showError, setOnline, clearAuthFormData, reset]
    );

    //Вход с данными из ref (после подстановки пароля встроенным сканером, чтобы не терять значение до применения setState)
    const performLoginWithFormRef = React.useCallback(() => {
        const form = formDataRef.current;
        if (!form) return;
        const s = (form.serverUrl != null ? String(form.serverUrl) : '').trim();
        const u = (form.username != null ? String(form.username) : '').trim();
        const p = (form.password != null ? String(form.password) : '').trim();
        if (!hideServerUrl || !form.serverUrl) {
            const urlResult = validateServerUrl(s, { emptyMessage: 'Укажите адрес сервера' });
            if (urlResult !== true) {
                showError(urlResult);
                return;
            }
        }
        if (!u) {
            showError('Укажите логин');
            return;
        }
        if (!p) {
            showError('Укажите пароль');
            return;
        }
        performLogin(form);
    }, [hideServerUrl, showError, performLogin]);

    //Обработчик входа (очистка локальных данных только при смене сервера относительно последнего успешного подключения)
    const handleLogin = React.useCallback(async () => {
        if (!validateForm()) {
            return;
        }

        const currentNormalized = normalizeServerUrl(serverUrl);
        const prevSession = await getAuthSession();
        const lastConnectedServerUrl = await getSetting(AUTH_SETTINGS_KEYS.LAST_CONNECTED_SERVER_URL).catch(() => '');
        const prevServerUrl = prevSession?.serverUrl || lastConnectedServerUrl || '';
        const prevNormalized = prevServerUrl ? normalizeServerUrl(prevServerUrl) : '';

        const connectionParamsChanged = prevNormalized !== '' && currentNormalized !== prevNormalized;

        if (connectionParamsChanged) {
            showInfo(AUTH_SERVER_CHANGE_CONFIRM_MESSAGE, {
                title: AUTH_SERVER_CHANGE_CONFIRM_TITLE,
                buttons: [
                    {
                        id: 'cancel',
                        title: AUTH_SERVER_CHANGE_CANCEL_BUTTON,
                        onPress: () => {}
                    },
                    {
                        id: 'confirm',
                        title: AUTH_SERVER_CHANGE_CONFIRM_BUTTON,
                        onPress: async () => {
                            await clearAuthSession();
                            await performLogin();
                        }
                    }
                ]
            });
        } else {
            await performLogin();
        }
    }, [validateForm, serverUrl, getAuthSession, getSetting, showInfo, clearAuthSession, performLogin]);

    //Обработчик выбора организации
    const handleSelectOrganization = React.useCallback(
        async org => {
            setShowOrgDialog(false);

            if (!pendingLoginData) {
                return;
            }

            const result = await selectCompany({
                serverUrl: pendingLoginData.serverUrl,
                sessionId: pendingLoginData.sessionId,
                user: pendingLoginData.user,
                company: org,
                savePassword: pendingLoginData.savePassword,
                loginCredentials: pendingLoginData.loginCredentials
            });

            if (!result.success) {
                showError(result.error || 'Ошибка выбора организации');
                return;
            }

            //Успешный вход
            setOnline();

            //Очищаем временные данные
            setPendingLoginData(null);
            setOrganizations([]);
            clearAuthFormData();
            clearAuthFormStore();

            //Сбрасываем навигацию
            reset();
        },
        [pendingLoginData, selectCompany, showError, setOnline, clearAuthFormData, reset]
    );

    //Обработчик отмены выбора организации
    const handleCancelOrganization = React.useCallback(() => {
        setShowOrgDialog(false);
        setPendingLoginData(null);
        setOrganizations([]);
    }, []);

    //Обработчик кнопки назад
    const handleBackPress = React.useCallback(() => {
        if (canGoBack) {
            goBack();
        }
    }, [canGoBack, goBack]);

    //Обработчик переключения показа пароля
    const handleTogglePassword = React.useCallback(value => {
        formDataRef.current.showPassword = value;
        setAuthFormStore({ showPassword: value });
        setShowPassword(value);
    }, []);

    //Обработчик переключения сохранения пароля
    const handleToggleSavePassword = React.useCallback(value => {
        formDataRef.current.savePassword = value;
        setAuthFormStore({ savePassword: value });
        setSavePassword(value);
    }, []);

    //При Enter в поле «Сервер» — фокус на логин
    const handleServerSubmitEditing = React.useCallback(() => {
        if (loginInputRef.current) {
            loginInputRef.current.focus();
        }
    }, []);

    //При Enter в поле «Логин» — фокус на пароль
    const handleLoginSubmitEditing = React.useCallback(() => {
        if (passwordInputRef.current) {
            passwordInputRef.current.focus();
        }
    }, []);

    //При Enter в поле «Пароль» — нажатие кнопки «Войти»
    const handlePasswordSubmitEditing = React.useCallback(() => {
        handleLogin();
    }, [handleLogin]);

    //Подстановка значения в поле формы по идентификатору (state, ref, store)
    const setAuthFieldValue = React.useCallback((fieldId, value) => {
        const v = value != null ? String(value) : '';
        if (fieldId === 'server') {
            formDataRef.current.serverUrl = v;
            setAuthFormStore({ serverUrl: v });
            setServerUrl(v);
        } else if (fieldId === 'login') {
            formDataRef.current.username = v;
            setAuthFormStore({ username: v });
            setUsername(v);
        } else if (fieldId === 'password') {
            formDataRef.current.password = v;
            setAuthFormStore({ password: v });
            setPassword(v);
        }
    }, []);

    //Перенос фокуса на поле формы по идентификатору
    const focusAuthField = React.useCallback(fieldId => {
        if (fieldId === 'server' && serverInputRef.current) {
            serverInputRef.current.focus();
        } else if (fieldId === 'login' && loginInputRef.current) {
            loginInputRef.current.focus();
        } else if (fieldId === 'password' && passwordInputRef.current) {
            passwordInputRef.current.focus();
        }
    }, []);

    //Обработчик встроенного сканера: подстановка в фокусное или первое доступное поле; при Enter — следующее поле или «Войти»
    const handleHardwareScan = useScanInputHandler({
        allowedFieldIds: allowedAuthFieldIds,
        focusedFieldRef,
        expectedNextTargetRef,
        setFieldValue: setAuthFieldValue,
        focusField: focusAuthField,
        parseSegments: parseScannedSegmentsForAuth,
        onSubmitForm: performLoginWithFormRef
    });

    const authScanHandlerRef = React.useRef(handleHardwareScan);
    authScanHandlerRef.current = handleHardwareScan;
    const stableAuthScanHandler = React.useCallback(barcode => {
        if (typeof authScanHandlerRef.current === 'function') authScanHandlerRef.current(barcode);
    }, []);

    //Регистрация обработчика встроенного сканера на экране AUTH
    React.useEffect(() => {
        registerHandler(scannerScreens.AUTH, stableAuthScanHandler);
        return function cleanup() {
            unregisterHandler(scannerScreens.AUTH);
        };
    }, [registerHandler, unregisterHandler, scannerScreens.AUTH, stableAuthScanHandler]);

    //Обработчик открытия меню
    const handleMenuOpen = React.useCallback(() => {
        setMenuVisible(true);
    }, []);

    //Обработчик закрытия меню
    const handleMenuClose = React.useCallback(() => {
        setMenuVisible(false);
    }, []);

    //Обработчик перехода в настройки
    const handleOpenSettings = React.useCallback(() => {
        navigate(SCREENS.SETTINGS);
    }, [navigate, SCREENS.SETTINGS]);

    //Обработчик показа информации о приложении
    const handleShowAbout = React.useCallback(() => {
        const appInfo = getAppInfo({
            mode,
            serverUrl,
            isDbReady
        });

        showInfo(appInfo, {
            title: APP_ABOUT_TITLE
        });
    }, [showInfo, mode, serverUrl, isDbReady]);

    //Обработчик выхода с экрана аутентификации: сброс стека, нельзя вернуться назад
    const logoutHandlerFromAuth = React.useMemo(() => {
        if (!isFromMenu) {
            return null;
        }
        return createLogoutHandler({
            logout,
            mode,
            setNotConnected,
            setInitialScreen,
            SCREENS,
            showError,
            showInfo,
            logoutConfirmTitle: LOGOUT_CONFIRM_TITLE,
            logoutConfirmMessage: LOGOUT_CONFIRM_MESSAGE,
            logoutButtonTitle: AUTH_BUTTON_LOGOUT,
            getConfirmButtonOptions,
            dialogButtonTypeError: DIALOG_BUTTON_TYPE.ERROR,
            dialogCancelButton: DIALOG_CANCEL_BUTTON
        });
    }, [isFromMenu, logout, mode, setNotConnected, setInitialScreen, SCREENS, showError, showInfo]);

    const handleLogoutFromAuth = React.useCallback(() => {
        if (logoutHandlerFromAuth) {
            logoutHandlerFromAuth.handleLogout();
        }
    }, [logoutHandlerFromAuth]);

    //Пункты бокового меню
    const menuItems = React.useMemo(() => {
        const items = [
            {
                id: MENU_ITEM_ID_SETTINGS,
                title: MENU_ITEM_SETTINGS,
                onPress: handleOpenSettings
            },
            {
                id: MENU_ITEM_ID_ABOUT,
                title: MENU_ITEM_ABOUT,
                onPress: handleShowAbout
            }
        ];

        if (isFromMenu) {
            items.push({
                id: MENU_ITEM_ID_DIVIDER,
                type: 'divider'
            });
            items.push({
                id: MENU_ITEM_ID_LOGOUT,
                title: MENU_ITEM_LOGOUT,
                onPress: handleLogoutFromAuth,
                textStyle: { color: APP_COLORS.error },
                iconColor: APP_COLORS.error
            });
        }

        return items;
    }, [handleOpenSettings, handleShowAbout, handleLogoutFromAuth, isFromMenu]);

    const shouldShowServerUrl = firstVisibleAuthField === 'server';

    return (
        <AdaptiveView padding={false}>
            <AppHeader showBackButton={canGoBack} onBackPress={handleBackPress} onMenuPress={handleMenuOpen} />

            <KeyboardAvoidingView
                style={styles.keyboardAvoidingView}
                behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
                keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 20}
            >
                <ScrollView
                    style={styles.scrollView}
                    contentContainerStyle={styles.scrollContent}
                    showsVerticalScrollIndicator={false}
                    keyboardShouldPersistTaps="handled"
                >
                    <View style={styles.logoContainer}>
                        <AppLogo size="large" />
                    </View>

                    <View style={styles.formContainer}>
                        <AppText style={styles.title} variant="h2" weight="bold">
                            {AUTH_SCREEN_TITLE}
                        </AppText>

                        {shouldShowServerUrl ? (
                            <AppInput
                                ref={serverInputRef}
                                key="server-input"
                                label="Сервер"
                                value={serverUrl}
                                onChangeText={handleServerUrlChange}
                                placeholder="https://example.com/api"
                                keyboardType="url"
                                autoCapitalize="none"
                                autoCorrect={false}
                                disabled={isLoading || isFromMenu}
                                blurOnSubmit={false}
                                returnKeyType="next"
                                onSubmitEditing={handleServerSubmitEditing}
                                onFocus={handleServerFocus}
                                onBlur={handleFieldBlur}
                            />
                        ) : null}

                        <AppInput
                            ref={loginInputRef}
                            key="login-input"
                            label="Логин"
                            value={username}
                            onChangeText={handleUsernameChange}
                            placeholder="Введите логин"
                            autoCapitalize="none"
                            autoCorrect={false}
                            disabled={isLoading || isFromMenu}
                            blurOnSubmit={false}
                            returnKeyType="next"
                            onSubmitEditing={handleLoginSubmitEditing}
                            onFocus={handleLoginFocus}
                            onBlur={handleFieldBlur}
                        />

                        <PasswordInput
                            ref={passwordInputRef}
                            key="password-input"
                            label="Пароль"
                            value={password}
                            onChangeText={handlePasswordChange}
                            placeholder="Введите пароль"
                            showPassword={showPassword}
                            onTogglePassword={handleTogglePassword}
                            disabled={isLoading}
                            blurOnSubmit={true}
                            returnKeyType="done"
                            onSubmitEditing={handlePasswordSubmitEditing}
                            onFocus={handlePasswordFocus}
                            onBlur={handleFieldBlur}
                        />

                        <View style={styles.switchContainer}>
                            <AppSwitch label="Сохранить пароль" value={savePassword} onValueChange={handleToggleSavePassword} disabled={isLoading} />
                        </View>

                        <AppButton
                            title={isLoading ? AUTH_BUTTON_LOADING : AUTH_BUTTON_LOGIN}
                            onPress={handleLogin}
                            disabled={isLoading || !isSettingsLoaded}
                            style={styles.loginButton}
                            textStyle={styles.loginButtonText}
                        />

                        {isFromMenu ? (
                            <AppButton
                                title={AUTH_BUTTON_LOGOUT}
                                onPress={handleLogoutFromAuth}
                                disabled={isLoading}
                                style={styles.logoutButton}
                                textStyle={styles.logoutButtonText}
                            />
                        ) : null}
                    </View>
                </ScrollView>
            </KeyboardAvoidingView>

            <SideMenu
                visible={menuVisible}
                onClose={handleMenuClose}
                items={menuItems}
                title={SIDE_MENU_TITLE}
                mode={mode}
                username={session?.userName}
                organization={session?.companyName}
            />

            <OrganizationSelectDialog
                visible={showOrgDialog}
                organizations={organizations}
                onSelect={handleSelectOrganization}
                onCancel={handleCancelOrganization}
                title={ORGANIZATION_SELECT_DIALOG_TITLE}
            />

            <LoadingOverlay visible={isLoading} message="Выполняется вход..." />
        </AdaptiveView>
    );
}

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

module.exports = AuthScreen;
