import { BootstrapDataManager } from '../BootstrapDataManager.mjs';
import { CaptchaProvider } from '../CaptchaProvider.mjs';
import { ClientsideServicesProvider } from '../ClientsideServicesProvider.mjs';
import { NetworkClient } from '../NetworkClient.mjs';
import { PKCEManager } from '../PKCEManager.mjs';
import { getB2BDataLayer, B2BSubscriptionService } from '../SubscriptionService.mjs';
import { buildFinalConfig, hasCustomApiEndpoint } from '../utils/config.mjs';
import { createAuthUrlHandler } from '../utils/createAuthUrlHandler.mjs';
import { writeB2BInternals } from '../utils/internal.mjs';
import { HeadlessB2BOAuthClient } from './HeadlessB2BOAuthClient.mjs';
import { B2BOneTapProvider } from './oneTap/B2BOneTapProvider.mjs';
import { checkB2BNotSSR, checkPublicToken } from '../../../core/src/utils/checks.mjs';
import { StateChangeClient } from '../../../core/src/StateChangeClient.mjs';
import { DFPProtectedAuthProvider } from '../../../core/src/DFPProtectedAuthProvider.mjs';
import { HeadlessB2BOrganizationClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BOrganizationClient.mjs';
import { HeadlessB2BDiscoveryClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BDiscoveryClient.mjs';
import { HeadlessB2BIDPClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BIDPClient.mjs';
import { HeadlessB2BImpersonationClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BImpersonationClient.mjs';
import { HeadlessB2BMagicLinksClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BMagicLinkClient.mjs';
import { logger } from '../../../core/src/utils/logger.mjs';
import { HeadlessB2BOTPsClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BOTPsClient.mjs';
import { HeadlessB2BPasswordsClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BPasswordsClient.mjs';
import { HeadlessB2BRBACClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BRBACClient.mjs';
import { HeadlessB2BRecoveryCodesClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BRecoveryCodesClient.mjs';
import { HeadlessB2BSCIMClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BSCIMClient.mjs';
import { HeadlessB2BSelfClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BSelfClient.mjs';
import { HeadlessB2BSessionClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BSessionClient.mjs';
import { HeadlessB2BSSOClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BSSOClient.mjs';
import { HeadlessB2BTOTPsClient } from '../../../core/src/HeadlessClients/b2b/HeadlessB2BTOTPsClient.mjs';
import '../../../core/src/HeadlessClients/HeadlessCryptoWalletClient.mjs';
import '../../../core/src/HeadlessClients/HeadlessMagicLinkClient.mjs';
import '../../../core/src/HeadlessClients/HeadlessPasswordClient.mjs';
import { SessionManager } from '../../../core/src/SessionManager.mjs';
import { VERTICAL_CONSUMER } from '../../../core/src/Vertical.mjs';
import { SearchDataManager } from '../../../core/src/SearchManager.mjs';

/**
 * A headless client used for invoking Stytch's B2B APIs.
 * The Stytch Headless Client can be used as a drop-in solution for authentication and session management.
 * Full documentation can be found {@link https://stytch.com/docs/b2b/sdks/javascript-sdk online}.
 *
 * @example
 * const stytch = new StytchB2BClient('public-token-<find yours in the stytch dashboard>');
 * stytch.magicLinks.email.loginOrCreate({
 *   email: 'sandbox@stytch.com',
 *   organization_id: 'organization-test-123',
 * });
 */ class StytchB2BClient {
    _subscriptionService;
    _sessionManager;
    _networkClient;
    _dataLayer;
    _stateChangeClient;
    // External API Clients
    magicLinks;
    session;
    /** @deprecated Please use client.self instead. This will be removed in a future release. */ member;
    self;
    organization;
    oauth;
    sso;
    discovery;
    passwords;
    otps;
    totp;
    recoveryCodes;
    rbac;
    scim;
    impersonation;
    idp;
    // External methods
    /**
   * Register a callback function to be invoked whenever certain state changes
   * occur, like a member or session object being updated.
   *
   * This is an alternative to more specific methods like `self.onChange` and
   * `session.onChange`. It can be helpful if you want to be notified of related
   * changes to different parts of state at once.
   *
   * If you are only interested in specific state changes, consider using more
   * specific methods like `self.onChange` and `session.onChange` instead.
   */ onStateChange;
    /**
   * Extracts token and token type from the current page URL's query parameters.
   * If the current URL do not have the required query params, this will return null.
   * Otherwise, returns an object { handled: boolean, tokenType: string, token: string }
   */ parseAuthenticateUrl;
    /**
   * Call this method to authenticate the user when the user has been redirected
   * to this page with a token in the query parameters, such as after OAuth
   * or through an email magic link. This method currently supports
   *
   * - Magic links
   * - OAuth
   * - SSO
   * - Impersonation
   *
   * If the current URL do not have the required query params, the promise returned will resolve to null.
   * If the token type is not supported (e.g. reset_password), the promise returned will resolve to this
   * object allowing you to handle the token.
   * {
   *   handled: false,
   *   tokenType: 'token_type',
   *   token: '<token>'
   * }
   */ authenticateByUrl;
    constructor(rawPublicToken, options){
        checkB2BNotSSR();
        // Intentionally check the raw public token so that we can log a correct error message,
        // but then coalesce to an empty string so that the UI components don't fail to render.
        checkPublicToken(rawPublicToken);
        const _PUBLIC_TOKEN = rawPublicToken ?? '';
        // Not casting to InternalStytchClientOptions since InternalStytchClientOptions is currently a superset
        const config = buildFinalConfig(this.constructor.name, options);
        const usingCustomApiEndpoint = hasCustomApiEndpoint(_PUBLIC_TOKEN, options);
        this._dataLayer = getB2BDataLayer(_PUBLIC_TOKEN, config);
        this._subscriptionService = new B2BSubscriptionService(_PUBLIC_TOKEN, this._dataLayer, {
            usingCustomApiEndpoint
        });
        this._stateChangeClient = new StateChangeClient(this._subscriptionService, {});
        this.onStateChange = (...args)=>this._stateChangeClient.onStateChange(...args);
        const additionalTelemetryDataFn = ()=>({
                stytch_member_id: this._dataLayer.state?.member?.member_id,
                stytch_member_session_id: this._dataLayer.state?.session?.member_session_id
            });
        const passwordsPKCEManager = new PKCEManager(this._dataLayer, 'passwords');
        const networkClient = new NetworkClient(_PUBLIC_TOKEN, this._dataLayer, config.endpoints.liveAPIURL, config.endpoints.testAPIURL, additionalTelemetryDataFn);
        this._networkClient = networkClient;
        const bootstrap = new BootstrapDataManager(_PUBLIC_TOKEN, networkClient, this._dataLayer);
        const captcha = new CaptchaProvider(bootstrap.getAsync());
        const dfpProtectedAuth = new DFPProtectedAuthProvider(_PUBLIC_TOKEN, config.endpoints.dfpBackendURL, config.endpoints.dfpCdnURL, bootstrap.getAsync(), captcha.executeRecaptcha);
        const clientsideServices = new ClientsideServicesProvider(config.endpoints.clientsideServicesIframeURL);
        const pkceManagerForOAuth = new PKCEManager(this._dataLayer, 'oauth');
        const oneTap = new B2BOneTapProvider(networkClient, pkceManagerForOAuth, bootstrap.getAsync());
        this.organization = new HeadlessB2BOrganizationClient(networkClient, networkClient, this._subscriptionService);
        this.member = new HeadlessB2BSelfClient(networkClient, networkClient, this._subscriptionService);
        this.self = new HeadlessB2BSelfClient(networkClient, networkClient, this._subscriptionService);
        this.session = new HeadlessB2BSessionClient(networkClient, this._subscriptionService);
        this.magicLinks = new HeadlessB2BMagicLinksClient(networkClient, this._subscriptionService, new PKCEManager(this._dataLayer, 'magic_links'), passwordsPKCEManager, bootstrap.getAsync(), dfpProtectedAuth);
        this.oauth = new HeadlessB2BOAuthClient(networkClient, this._subscriptionService, pkceManagerForOAuth, bootstrap.getAsync(), {
            publicToken: _PUBLIC_TOKEN,
            testAPIURL: config.endpoints.testAPIURL,
            liveAPIURL: config.endpoints.liveAPIURL
        }, dfpProtectedAuth, oneTap);
        this.sso = new HeadlessB2BSSOClient(networkClient, this._subscriptionService, new PKCEManager(this._dataLayer, 'sso'), bootstrap.getAsync(), {
            publicToken: _PUBLIC_TOKEN,
            testAPIURL: config.endpoints.testAPIURL,
            liveAPIURL: config.endpoints.liveAPIURL
        }, dfpProtectedAuth);
        this.discovery = new HeadlessB2BDiscoveryClient(networkClient, this._subscriptionService);
        this.passwords = new HeadlessB2BPasswordsClient(networkClient, this._subscriptionService, passwordsPKCEManager, bootstrap.getAsync(), dfpProtectedAuth);
        this.otps = new HeadlessB2BOTPsClient(networkClient, this._subscriptionService, dfpProtectedAuth);
        this.totp = new HeadlessB2BTOTPsClient(networkClient, this._subscriptionService, dfpProtectedAuth);
        this.recoveryCodes = new HeadlessB2BRecoveryCodesClient(networkClient, this._subscriptionService, dfpProtectedAuth);
        this.rbac = new HeadlessB2BRBACClient(bootstrap.getSync(), bootstrap.getAsync(), this._subscriptionService);
        this.scim = new HeadlessB2BSCIMClient(this._networkClient, this._subscriptionService);
        this.impersonation = new HeadlessB2BImpersonationClient(this._networkClient, this._subscriptionService, dfpProtectedAuth);
        this.idp = new HeadlessB2BIDPClient(networkClient);
        this._sessionManager = new SessionManager(this._subscriptionService, this.session, _PUBLIC_TOKEN, {
            keepSessionAlive: config.keepSessionAlive
        });
        const searchManager = new SearchDataManager(networkClient, dfpProtectedAuth);
        // If the session does not exist in localstorage (like if we are in an iframe)
        // then the cookie might still be set and we can retrieve the session via an API call.
        // If a custom API endpoint is being used, the session may be being managed by
        // HttpOnly cookies, which we can't detect.
        if (usingCustomApiEndpoint || this._dataLayer.readSessionCookie().session_token) {
            this._sessionManager.performBackgroundRefresh();
        }
        const { authenticateByUrl, parseAuthenticateUrl } = createAuthUrlHandler({
            discovery: (token)=>this.magicLinks.discovery.authenticate({
                    discovery_magic_links_token: token
                }),
            discovery_oauth: (token)=>this.oauth.discovery.authenticate({
                    discovery_oauth_token: token
                }),
            oauth: (token, options)=>this.oauth.authenticate({
                    oauth_token: token,
                    ...options
                }),
            sso: (token, options)=>this.sso.authenticate({
                    sso_token: token,
                    ...options
                }),
            multi_tenant_magic_links: (token, options)=>this.magicLinks.authenticate({
                    magic_links_token: token,
                    ...options
                }),
            multi_tenant_impersonation: (token)=>this.impersonation.authenticate({
                    impersonation_token: token
                })
        });
        this.authenticateByUrl = authenticateByUrl;
        this.parseAuthenticateUrl = parseAuthenticateUrl;
        networkClient.logEvent({
            name: 'b2b_sdk_instance_instantiated',
            details: {
                event_callback_registered: false,
                error_callback_registered: false,
                success_callback_registered: false
            }
        });
        bootstrap.getAsync().then((bootstrapData)=>{
            if (bootstrapData.vertical === VERTICAL_CONSUMER) {
                logger.error('This application is using a Stytch client for B2B projects, but the public token is for a Stytch Consumer project. Use a Consumer Stytch client instead, or verify that the public token is correct.');
            }
        });
        const internals = {
            bootstrap,
            clientsideServices,
            publicToken: _PUBLIC_TOKEN,
            searchManager,
            dataLayer: this._dataLayer,
            networkClient: networkClient,
            oneTap
        };
        writeB2BInternals(this, internals);
    }
}

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