import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * LoginScreen — Silent token refresh overlay for the /login slash command (v2).
 *
 * On mount, reads the stored refresh token from ~/.ampli.json and exchanges
 * it for a new access token via the Amplitude OAuth2 token endpoint.
 * No browser required. Falls back gracefully if no token is stored or if
 * the refresh fails.
 */
import { Box, Text } from 'ink';
import { useState, useEffect, useRef } from 'react';
import { Colors, Icons } from '../styles.js';
import { BrailleSpinner } from '../components/BrailleSpinner.js';
import { DEFAULT_AMPLITUDE_ZONE } from '../../../lib/constants.js';
import { resolveZone } from '../../../lib/zone-resolution.js';
var Phase;
(function (Phase) {
    Phase["Refreshing"] = "refreshing";
    Phase["Success"] = "success";
    Phase["NoToken"] = "no-token";
    Phase["Error"] = "error";
})(Phase || (Phase = {}));
export const LoginScreen = ({ store, onComplete }) => {
    const [phase, setPhase] = useState(Phase.Refreshing);
    const [errorMsg, setErrorMsg] = useState(null);
    // Tracks the auto-dismiss timer so unmount clears it. Without this
    // ref + cleanup, navigating away from the overlay (Esc back-nav,
    // outer screen swap, ScreenErrorBoundary retry) leaves a dangling
    // setTimeout that fires `onComplete` against an unmounted overlay
    // 1.5–2.5s later — popping the wrong overlay and producing visible
    // navigation glitches.
    const dismissTimerRef = useRef(null);
    const mountedRef = useRef(true);
    useEffect(() => {
        return () => {
            mountedRef.current = false;
            if (dismissTimerRef.current !== null) {
                clearTimeout(dismissTimerRef.current);
                dismissTimerRef.current = null;
            }
        };
    }, []);
    /** Schedule onComplete; refuses to schedule on an unmounted screen. */
    const scheduleDismiss = (ms) => {
        if (!mountedRef.current)
            return;
        if (dismissTimerRef.current !== null)
            clearTimeout(dismissTimerRef.current);
        dismissTimerRef.current = setTimeout(() => {
            dismissTimerRef.current = null;
            if (mountedRef.current)
                onComplete();
        }, ms);
    };
    useEffect(() => {
        void (async () => {
            try {
                const [{ getStoredToken, getStoredUser, storeToken }, { refreshAccessToken },] = await Promise.all([
                    import('../../../utils/ampli-settings.js'),
                    import('../../../utils/oauth.js'),
                ]);
                if (!mountedRef.current)
                    return;
                const user = getStoredUser();
                // readDisk: true — login runs before the RegionSelect gate; disk
                // tiers are the authoritative source for intent here.
                const zone = resolveZone(store.session, DEFAULT_AMPLITUDE_ZONE, {
                    readDisk: true,
                });
                const stored = getStoredToken(user?.id, zone);
                if (!stored) {
                    if (!mountedRef.current)
                        return;
                    setPhase(Phase.NoToken);
                    scheduleDismiss(2500);
                    return;
                }
                const result = await refreshAccessToken(stored.refreshToken, zone);
                if (!mountedRef.current)
                    return;
                // Persist updated tokens to ~/.ampli.json
                if (user) {
                    storeToken(user, {
                        accessToken: result.accessToken,
                        idToken: result.idToken,
                        refreshToken: result.refreshToken,
                        expiresAt: result.expiresAt,
                    });
                }
                // Patch the live session credentials without re-running auth flow
                store.updateAccessToken(result.accessToken);
                setPhase(Phase.Success);
                scheduleDismiss(1500);
            }
            catch (err) {
                // Bail BEFORE touching disk if the user already navigated away —
                // otherwise an in-flight refresh that throws after unmount would
                // wipe `~/.ampli.json` for an overlay the user can no longer see.
                // (Pre-fix this could happen on Esc-back-nav, outer screen swap,
                // ScreenErrorBoundary retry, or any slash command that pops the
                // overlay before the network call resolves.)
                if (!mountedRef.current)
                    return;
                // Do NOT call clearStoredCredentials() here. It writes `{}` to
                // ~/.ampli.json, blowing away every user/zone entry — not just
                // the one we were trying to refresh. A failed silent refresh is
                // already handled gracefully on the next run by the AuthScreen
                // (which falls back to fresh browser auth when the stored token
                // is invalid). Surfacing the error to the user is enough.
                setErrorMsg(err instanceof Error ? err.message : 'Unknown error');
                setPhase(Phase.Error);
                scheduleDismiss(2500);
            }
        })();
    }, []);
    return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [_jsx(Text, { bold: true, color: Colors.accent, children: "Re-authenticate" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [phase === Phase.Refreshing && (_jsxs(Box, { gap: 1, children: [_jsx(BrailleSpinner, {}), _jsxs(Text, { color: Colors.active, children: ["Refreshing credentials", Icons.ellipsis] })] })), phase === Phase.Success && (_jsxs(Text, { color: Colors.success, children: [Icons.checkmark, " Credentials refreshed."] })), phase === Phase.NoToken && (_jsx(Text, { color: Colors.secondary, children: "No stored credentials found. Restart the wizard to re-authenticate." })), phase === Phase.Error && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: Colors.error, children: ["Refresh failed: ", errorMsg] }), _jsx(Text, { color: Colors.secondary, children: "Restart the wizard to re-authenticate." })] }))] })] }));
};
