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

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

const React = require('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 { useAppLocalDbContext } = require('../components/layout/AppLocalDbProvider');
const { useAppAuthContext } = require('../components/layout/AppAuthProvider');
const { getAppInfo } = require('../utils/appInfo');
const { isServerUrlFieldVisible } = require('../utils/loginFormUtils');
const { normalizeServerUrl, validateServerUrl } = require('../utils/validation');
const { AUTH_SETTINGS_KEYS } = require('../config/authConfig');
const styles = require('../styles/screens/AuthScreen.styles');

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

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

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

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

    //Состояние отображения
    const [hideServerUrl, setHideServerUrl] = React.useState(false);
    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 для хранения актуальных значений формы (для синхронизации при размонтировании)
    const formDataRef = React.useRef({ serverUrl, username, password, savePassword });

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

    //Обновление ref при изменении значений формы
    React.useEffect(() => {
        formDataRef.current = { serverUrl, username, password, savePassword };
    }, [serverUrl, username, password, savePassword]);

    //Синхронизация данных формы с контекстом при размонтировании компонента
    React.useEffect(() => {
        return () => {
            updateAuthFormData(formDataRef.current);
        };
    }, [updateAuthFormData]);

    //При готовности БД один раз подставляем сохранённый логин в поле (если оно пустое)
    React.useEffect(() => {
        if (!isDbReady || savedLoginFilledRef.current) {
            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(() => {});
        return () => {
            cancelled = true;
        };
    }, [isDbReady, getSetting]);

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

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

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

                if (savedServerUrl) {
                    setServerUrl(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) {
                console.error('Ошибка загрузки credentials из меню:', 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) {
                console.warn('Резервная загрузка логина:', e);
            }
        };

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

    //Загрузка настроек при готовности БД
    //В т.ч. при работе в оффлайн подставляем сохранённый логин и при необходимости пароль
    React.useEffect(() => {
        //Пропускаем если БД не готова, уже загружали или открыто из меню
        if (!isDbReady || initialLoadRef.current || isFromMenu) {
            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);
                }

                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);
                }
            } catch (loadError) {
                console.error('Ошибка загрузки настроек авторизации:', loadError);
            } finally {
                setIsSettingsLoaded(true);
            }
        };

        loadSettings();
    }, [isDbReady, isFromMenu, 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 () => {
        let idleTimeout = null;
        try {
            idleTimeout = await getSetting(AUTH_SETTINGS_KEYS.IDLE_TIMEOUT);
        } catch (settingError) {
            console.warn('Ошибка получения таймаута:', settingError);
        }

        const result = await login({
            serverUrl: serverUrl.trim(),
            user: username.trim(),
            password: password.trim(),
            timeout: idleTimeout ? parseInt(idleTimeout, 10) : null,
            savePassword
        });

        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;
        }

        showSuccess('Вход выполнен успешно');
        setOnline();
        clearAuthFormData();
        reset();
    }, [login, serverUrl, username, password, savePassword, getSetting, showError, showSuccess, setOnline, clearAuthFormData, reset]);

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

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

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

        if (connectionParamsChanged) {
            showInfo('При смене параметров подключения все локальные данные будут сброшены. Продолжить?', {
                title: 'Подтверждение входа',
                buttons: [
                    {
                        id: 'cancel',
                        title: 'Отмена',
                        onPress: () => {}
                    },
                    {
                        id: 'confirm',
                        title: 'Продолжить',
                        onPress: async () => {
                            await clearAuthSession();
                            await clearInspections();
                            await performLogin();
                        }
                    }
                ]
            });
        } else {
            await performLogin();
        }
    }, [validateForm, serverUrl, getAuthSession, getSetting, showInfo, clearAuthSession, clearInspections, 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;
            }

            //Успешный вход
            showSuccess('Вход выполнен успешно');
            setOnline();

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

            //Очищаем данные формы в контексте
            clearAuthFormData();

            //Сбрасываем навигацию
            reset();
        },
        [pendingLoginData, selectCompany, showError, showSuccess, 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 => {
        setShowPassword(value);
    }, []);

    //Обработчик переключения сохранения пароля
    const handleToggleSavePassword = React.useCallback(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]);

    //Обработчик открытия меню
    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: 'Информация о приложении'
        });
    }, [showInfo, mode, serverUrl, isDbReady]);

    //Пункты бокового меню
    const menuItems = React.useMemo(() => {
        return [
            {
                id: 'settings',
                title: 'Настройки',
                onPress: handleOpenSettings
            },
            {
                id: 'about',
                title: 'О приложении',
                onPress: handleShowAbout
            }
        ];
    }, [handleOpenSettings, handleShowAbout]);

    //Поле сервера показываем, если настройка выключена или сервер не указан
    const shouldShowServerUrl = isServerUrlFieldVisible(hideServerUrl, serverUrl);

    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">
                            Вход в приложение
                        </AppText>

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

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

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

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

                        <AppButton
                            title={isLoading ? 'Вход...' : 'Войти'}
                            onPress={handleLogin}
                            disabled={isLoading || !isSettingsLoaded}
                            style={styles.loginButton}
                            textStyle={styles.loginButtonText}
                        />
                    </View>
                </ScrollView>
            </KeyboardAvoidingView>

            <SideMenu
                visible={menuVisible}
                onClose={handleMenuClose}
                items={menuItems}
                title="Меню"
                mode={mode}
                username={session?.userName}
                organization={session?.companyName}
            />

            <OrganizationSelectDialog
                visible={showOrgDialog}
                organizations={organizations}
                onSelect={handleSelectOrganization}
                onCancel={handleCancelOrganization}
                title="Выберите организацию"
            />

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

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

module.exports = AuthScreen;
