import { DisabledDFPProtectedAuthProvider } from '../../DFPProtectedAuthProvider.mjs';
import { validateInDev } from '../../utils/dev.mjs';

const DefaultDynamicConfig$4 = Promise.resolve({
    pkceRequiredForEmailMagicLinks: false
});
class HeadlessB2BMagicLinksClient {
    _networkClient;
    _subscriptionService;
    _pkceManager;
    _passwordResetPKCEManager;
    _config;
    dfpProtectedAuth;
    email;
    authenticate;
    discovery;
    constructor(_networkClient, _subscriptionService, _pkceManager, _passwordResetPKCEManager, _config = DefaultDynamicConfig$4, dfpProtectedAuth = DisabledDFPProtectedAuthProvider()){
        this._networkClient = _networkClient;
        this._subscriptionService = _subscriptionService;
        this._pkceManager = _pkceManager;
        this._passwordResetPKCEManager = _passwordResetPKCEManager;
        this._config = _config;
        this.dfpProtectedAuth = dfpProtectedAuth;
        this.email = {
            invite: async (data)=>{
                validateInDev('stytch.magicLinks.email.invite', data, {
                    email_address: 'string',
                    invite_redirect_url: 'optionalString',
                    invite_template_id: 'optionalString',
                    name: 'optionalString',
                    locale: 'optionalString',
                    roles: 'optionalStringArray',
                    invite_expiration_minutes: 'optionalNumber'
                });
                return this._networkClient.fetchSDK({
                    url: '/b2b/magic_links/email/invite',
                    body: data,
                    method: 'POST'
                });
            },
            loginOrSignup: async (data)=>{
                validateInDev('stytch.magicLinks.email.loginOrSignup', data, {
                    email_address: 'string',
                    organization_id: 'string',
                    login_redirect_url: 'optionalString',
                    login_template_id: 'optionalString',
                    signup_redirect_url: 'optionalString',
                    signup_template_id: 'optionalString',
                    locale: 'optionalString',
                    login_expiration_minutes: 'optionalNumber',
                    signup_expiration_minutes: 'optionalNumber'
                });
                const pkce_code_challenge = await this.getCodeChallenge();
                const requestBody = {
                    ...data,
                    pkce_code_challenge
                };
                return this._networkClient.fetchSDK({
                    url: '/b2b/magic_links/email/login_or_signup',
                    body: requestBody,
                    method: 'POST'
                });
            },
            discovery: {
                send: async (data)=>{
                    validateInDev('stytch.magicLinks.email.discovery.send', data, {
                        email_address: 'string',
                        discovery_redirect_url: 'optionalString',
                        login_template_id: 'optionalString',
                        locale: 'optionalString',
                        discovery_expiration_minutes: 'optionalNumber'
                    });
                    const { dfp_telemetry_id, captcha_token } = await this.dfpProtectedAuth.getDFPTelemetryIDAndCaptcha();
                    const pkce_code_challenge = await this.getCodeChallenge();
                    const requestBody = {
                        ...data,
                        pkce_code_challenge,
                        dfp_telemetry_id,
                        captcha_token
                    };
                    return this._networkClient.retriableFetchSDK({
                        url: '/b2b/magic_links/email/discovery/send',
                        body: requestBody,
                        method: 'POST',
                        retryCallback: this.dfpProtectedAuth.retryWithCaptchaAndDFP
                    });
                }
            }
        };
        this.authenticate = this._subscriptionService.withUpdateSession(async (data)=>{
            validateInDev('stytch.magicLinks.authenticate', data, {
                magic_links_token: 'string',
                session_duration_minutes: 'number',
                locale: 'optionalString'
            });
            // When a user resets their password with PKCE turned on, they create a pkPair in the 'passwords' namespace.
            // However, when the user gets the reset password email, they have the option to log in without a password.
            // This redirects them to the magic link authenticate flow, which automatically looks for the pkce code_verifier
            // in the 'magic_links' namespace, breaking the flow. Unfortunately we won't know for sure in the eml authenticate call
            // whether or not the user is coming from a password reset flow. To handle this, we have to try to authenticate with
            // both the 'passwords' and 'magic_links' code_verifiers.
            const passwordResetPKPair = await this._passwordResetPKCEManager.getPKPair();
            let resp = null;
            if (passwordResetPKPair?.code_verifier) {
                try {
                    resp = await this.handlePKCEForAuthenticate(this._passwordResetPKCEManager, data);
                } catch (e) {
                    if (e.message.includes('pkce')) {
                        // If pkce-related error, fall back to magic links code_verifier
                        // eslint-disable-next-line no-console
                        console.log('Authenticate with passwords pkce namespace failed. Falling back to authenticate with magic_links namespace.');
                    } else {
                        throw e;
                    }
                }
            }
            if (!resp) {
                resp = await this.handlePKCEForAuthenticate(this._pkceManager, data);
            }
            return resp;
        });
        this.discovery = {
            authenticate: this._subscriptionService.withUpdateSession(async (data)=>{
                validateInDev('stytch.magicLinks.discovery.authenticate', data, {
                    discovery_magic_links_token: 'string'
                });
                const pkPair = await this._pkceManager.getPKPair();
                const { dfp_telemetry_id, captcha_token } = await this.dfpProtectedAuth.getDFPTelemetryIDAndCaptcha();
                const requestBody = {
                    pkce_code_verifier: pkPair?.code_verifier,
                    dfp_telemetry_id,
                    captcha_token,
                    ...data
                };
                const resp = await this._networkClient.retriableFetchSDK({
                    url: '/b2b/magic_links/discovery/authenticate',
                    body: requestBody,
                    method: 'POST',
                    retryCallback: this.dfpProtectedAuth.retryWithCaptchaAndDFP
                });
                this._pkceManager.clearPKPair();
                return resp;
            })
        };
    }
    async getCodeChallenge() {
        const { pkceRequiredForEmailMagicLinks } = await this._config;
        if (!pkceRequiredForEmailMagicLinks) {
            return undefined;
        }
        let keyPair = await this._pkceManager.getPKPair();
        if (keyPair) {
            return keyPair.code_challenge;
        }
        keyPair = await this._pkceManager.startPKCETransaction();
        return keyPair.code_challenge;
    }
    async handlePKCEForAuthenticate(pkceManager, data) {
        const pkPair = await pkceManager.getPKPair();
        const { dfp_telemetry_id, captcha_token } = await this.dfpProtectedAuth.getDFPTelemetryIDAndCaptcha();
        const requestBody = {
            pkce_code_verifier: pkPair?.code_verifier,
            dfp_telemetry_id,
            captcha_token,
            intermediate_session_token: await this._subscriptionService.getIntermediateSessionToken() || undefined,
            ...data
        };
        const resp = await this._networkClient.retriableFetchSDK({
            url: '/b2b/magic_links/authenticate',
            body: requestBody,
            method: 'POST',
            retryCallback: this.dfpProtectedAuth.retryWithCaptchaAndDFP
        });
        pkceManager.clearPKPair();
        return resp;
    }
}

export { HeadlessB2BMagicLinksClient };
//# sourceMappingURL=HeadlessB2BMagicLinkClient.mjs.map
