import { omitUser } from '../utils/index.mjs';
import { validateInDev } from '../utils/dev.mjs';
import { UNRECOVERABLE_ERROR_TYPES } from '../public/SDKErrors.mjs';

class HeadlessSessionClient {
    _networkClient;
    _subscriptionService;
    authenticate;
    exchangeAccessToken;
    attest;
    constructor(_networkClient, _subscriptionService){
        this._networkClient = _networkClient;
        this._subscriptionService = _subscriptionService;
        this.authenticate = this._subscriptionService.withUpdateSession(this._authenticate);
        this.exchangeAccessToken = this._subscriptionService.withUpdateSession(async (data)=>{
            validateInDev('stytch.session.exchangeAccessToken', data, {
                access_token: 'string',
                session_duration_minutes: 'number'
            });
            const resp = await this._networkClient.fetchSDK({
                url: '/sessions/exchange_access_token',
                body: data,
                method: 'POST'
            });
            return omitUser(resp);
        });
        this.attest = this._subscriptionService.withUpdateSession(async (data)=>{
            validateInDev('stytch.session.attest', data, {
                profile_id: 'string',
                token: 'string',
                session_duration_minutes: 'optionalNumber'
            });
            return this._networkClient.fetchSDK({
                url: '/sessions/attest',
                body: data,
                method: 'POST'
            });
        });
    }
    getSync = ()=>{
        return this._subscriptionService.getSession();
    };
    getInfo = ()=>{
        const session = this.getSync();
        const fromCache = this._subscriptionService.getFromCache();
        return {
            session,
            fromCache
        };
    };
    onChange = (callback)=>{
        let lastVal = this._subscriptionService.getSession();
        const listener = (state)=>{
            if (state?.session !== lastVal) {
                lastVal = state?.session ?? null;
                callback(lastVal);
            }
        };
        return this._subscriptionService.subscribeToState(listener);
    };
    revoke = async (options)=>{
        /**
     * Revoke destroys the local state if the API request is successful
     * or if we return an unrecoverable error (user is unauthenticated)
     * or if the developer passses in a forceClear option.
     * If the API request returns a recoverable error (the user is offline),
     * we do not destroy the local state to let the developer manually add retry
     * logic to call revoke again.
     */ try {
            const resp = await this._networkClient.fetchSDK({
                url: `/sessions/revoke`,
                method: 'POST'
            });
            this._subscriptionService.destroyState();
            return resp;
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        } catch (error) {
            if (options?.forceClear) {
                this._subscriptionService.destroyState();
            } else if (UNRECOVERABLE_ERROR_TYPES.includes(error.error_type)) {
                this._subscriptionService.destroyState();
            }
            throw error;
        }
    };
    _authenticate = async (options)=>{
        const initialSession = this._subscriptionService.getSession();
        const isSessionStale = ()=>initialSession?.session_id !== this._subscriptionService.getSession()?.session_id;
        try {
            const requestBody = {
                session_duration_minutes: options?.session_duration_minutes
            };
            const resp = await this._networkClient.fetchSDK({
                url: '/sessions/authenticate',
                body: requestBody,
                method: 'POST'
            });
            if (isSessionStale()) {
                // [SDK-1336] The session was updated out from under us while the
                // request was in flight; discard the response and retry
                return this._authenticate(options);
            }
            return omitUser(resp);
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        } catch (error) {
            if (isSessionStale()) {
                // [SDK-1336] The session was updated out from under us while the
                // request was in flight; discard the response and retry
                return this._authenticate(options);
            }
            if (UNRECOVERABLE_ERROR_TYPES.includes(error.error_type)) {
                this._subscriptionService.destroySession();
            }
            throw error;
        }
    };
    getTokens() {
        return this._subscriptionService.getTokens();
    }
    updateSession(tokens) {
        validateInDev('stytch.session.updateSession', tokens, {
            session_token: 'string',
            session_jwt: 'optionalString'
        });
        this._subscriptionService.updateTokens(tokens);
    }
}

export { HeadlessSessionClient };
//# sourceMappingURL=HeadlessSessionClient.mjs.map
