import { omitUser } from '../utils/index.mjs';

const DefaultDynamicConfig$1 = Promise.resolve({
    pkceRequiredForEmailMagicLinks: false
});
class HeadlessMagicLinksClient {
    _networkClient;
    _subscriptionService;
    _pkceManager;
    _passwordResetPKCEManager;
    _config;
    dfpProtectedAuth;
    email;
    authenticate;
    constructor(_networkClient, _subscriptionService, _pkceManager, _passwordResetPKCEManager, _config = DefaultDynamicConfig$1, dfpProtectedAuth){
        this._networkClient = _networkClient;
        this._subscriptionService = _subscriptionService;
        this._pkceManager = _pkceManager;
        this._passwordResetPKCEManager = _passwordResetPKCEManager;
        this._config = _config;
        this.dfpProtectedAuth = dfpProtectedAuth;
        this.email = {
            loginOrCreate: async (email, options = {})=>{
                const { pkceRequiredForEmailMagicLinks } = await this._config;
                let code_challenge = undefined;
                if (pkceRequiredForEmailMagicLinks) {
                    code_challenge = await this.getCodeChallenge();
                }
                const { dfp_telemetry_id, captcha_token } = await this.dfpProtectedAuth.getDFPTelemetryIDAndCaptcha();
                const requestBody = {
                    ...options,
                    email,
                    code_challenge,
                    captcha_token,
                    dfp_telemetry_id
                };
                return this._networkClient.retriableFetchSDK({
                    url: '/magic_links/email/login_or_create',
                    body: requestBody,
                    method: 'POST',
                    retryCallback: this.dfpProtectedAuth.retryWithCaptchaAndDFP
                });
            },
            send: async (email, options = {})=>{
                const { pkceRequiredForEmailMagicLinks } = await this._config;
                let code_challenge = undefined;
                if (pkceRequiredForEmailMagicLinks) {
                    code_challenge = await this.getCodeChallenge();
                }
                const { dfp_telemetry_id, captcha_token } = await this.dfpProtectedAuth.getDFPTelemetryIDAndCaptcha();
                const requestBody = {
                    ...options,
                    email,
                    code_challenge,
                    captcha_token,
                    dfp_telemetry_id
                };
                const isLoggedIn = !!this._subscriptionService.getSession();
                const endpoint = isLoggedIn ? '/magic_links/email/send/secondary' : '/magic_links/email/send/primary';
                return this._networkClient.retriableFetchSDK({
                    url: endpoint,
                    body: requestBody,
                    method: 'POST',
                    retryCallback: this.dfpProtectedAuth.retryWithCaptchaAndDFP
                });
            }
        };
        this.authenticate = this._subscriptionService.withUpdateSession(async (token, options)=>{
            // 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, {
                        token,
                        ...options
                    });
                } 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, {
                    token,
                    ...options
                });
            }
            return omitUser(resp);
        });
    }
    async getCodeChallenge() {
        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 requestBody = {
            code_verifier: pkPair?.code_verifier,
            ...data
        };
        const resp = await this._networkClient.fetchSDK({
            url: '/magic_links/authenticate',
            body: requestBody,
            method: 'POST'
        });
        pkceManager.clearPKPair();
        return resp;
    }
}

export { HeadlessMagicLinksClient };
//# sourceMappingURL=HeadlessMagicLinkClient.mjs.map
