"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const helpers_1 = require("../../common/helpers");
class ApplePortalSessionService {
    constructor($applePortalCookieService, $errors, $httpClient, $logger, $prompter) {
        this.$applePortalCookieService = $applePortalCookieService;
        this.$errors = $errors;
        this.$httpClient = $httpClient;
        this.$logger = $logger;
        this.$prompter = $prompter;
        this.loginConfigEndpoint = "https://appstoreconnect.apple.com/olympus/v1/app/config?hostname=itunesconnect.apple.com";
        this.defaultLoginConfig = {
            authServiceUrl: "https://idmsa.apple.com/appleautcodh",
            authServiceKey: "e0b80c3bf78523bfe80974d320935bfa30add02e1bff88ec2166c6bd5a706c42"
        };
    }
    createUserSession(credentials, opts) {
        return __awaiter(this, void 0, void 0, function* () {
            const loginResult = yield this.login(credentials, opts);
            if (!opts || !opts.sessionBase64) {
                if (loginResult.isTwoFactorAuthenticationEnabled) {
                    const authServiceKey = (yield this.getLoginConfig()).authServiceKey;
                    yield this.handleTwoFactorAuthentication(loginResult.scnt, loginResult.xAppleIdSessionId, authServiceKey);
                }
                const sessionResponse = yield this.$httpClient.httpRequest({
                    url: "https://appstoreconnect.apple.com/olympus/v1/session",
                    method: "GET",
                    headers: {
                        'Cookie': this.$applePortalCookieService.getUserSessionCookie()
                    }
                });
                this.$applePortalCookieService.updateUserSessionCookie(sessionResponse.headers["set-cookie"]);
            }
            const userDetailsResponse = yield this.$httpClient.httpRequest({
                url: "https://appstoreconnect.apple.com/WebObjects/iTunesConnect.woa/ra/user/detail",
                method: "GET",
                headers: {
                    'Content-Type': 'application/json',
                    'Cookie': this.$applePortalCookieService.getUserSessionCookie(),
                }
            });
            this.$applePortalCookieService.updateUserSessionCookie(userDetailsResponse.headers["set-cookie"]);
            const userdDetails = JSON.parse(userDetailsResponse.body).data;
            const result = Object.assign({}, userdDetails, loginResult, { userSessionCookie: this.$applePortalCookieService.getUserSessionCookie() });
            return result;
        });
    }
    createWebSession(contentProviderId, dsId) {
        return __awaiter(this, void 0, void 0, function* () {
            const webSessionResponse = yield this.$httpClient.httpRequest({
                url: "https://appstoreconnect.apple.com/WebObjects/iTunesConnect.woa/ra/v1/session/webSession",
                method: "POST",
                body: JSON.stringify({
                    contentProviderId,
                    dsId,
                    ipAddress: null
                }),
                headers: {
                    'Accept': 'application/json, text/plain, */*',
                    'Accept-Encoding': 'gzip, deflate, br',
                    'X-Csrf-Itc': 'itc',
                    'Content-Type': 'application/json;charset=UTF-8',
                    'Cookie': this.$applePortalCookieService.getUserSessionCookie()
                }
            });
            const webSessionCookie = this.$applePortalCookieService.getWebSessionCookie(webSessionResponse.headers["set-cookie"]);
            return webSessionCookie;
        });
    }
    login(credentials, opts) {
        return __awaiter(this, void 0, void 0, function* () {
            const result = {
                scnt: null,
                xAppleIdSessionId: null,
                isTwoFactorAuthenticationEnabled: false,
                areCredentialsValid: true
            };
            if (opts && opts.sessionBase64) {
                const decodedSession = Buffer.from(opts.sessionBase64, "base64").toString("utf8");
                this.$applePortalCookieService.updateUserSessionCookie([decodedSession]);
                result.isTwoFactorAuthenticationEnabled = decodedSession.indexOf("DES") > -1;
            }
            else {
                try {
                    yield this.loginCore(credentials);
                }
                catch (err) {
                    const statusCode = err && err.response && err.response.statusCode;
                    result.areCredentialsValid = statusCode !== 401 && statusCode !== 403;
                    result.isTwoFactorAuthenticationEnabled = statusCode === 409;
                    if (result.isTwoFactorAuthenticationEnabled && opts && opts.requireApplicationSpecificPassword && !opts.applicationSpecificPassword) {
                        this.$errors.failWithoutHelp(`Your account has two-factor authentication enabled but --appleApplicationSpecificPassword option is not provided.
To generate an application-specific password, please go to https://appleid.apple.com/account/manage.
This password will be used for the iTunes Transporter, which is used to upload your application.`);
                    }
                    if (result.isTwoFactorAuthenticationEnabled && opts && opts.requireInteractiveConsole && !helpers_1.isInteractive()) {
                        this.$errors.failWithoutHelp(`Your account has two-factor authentication enabled, but your console is not interactive.
For more details how to set up your environment, please execute "tns publish ios --help".`);
                    }
                    const headers = (err && err.response && err.response.headers) || {};
                    result.scnt = headers.scnt;
                    result.xAppleIdSessionId = headers['x-apple-id-session-id'];
                }
            }
            return result;
        });
    }
    loginCore(credentials) {
        return __awaiter(this, void 0, void 0, function* () {
            const loginConfig = yield this.getLoginConfig();
            const loginUrl = `${loginConfig.authServiceUrl}/auth/signin`;
            const headers = {
                'Content-Type': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'X-Apple-Widget-Key': loginConfig.authServiceKey,
                'Accept': 'application/json, text/javascript'
            };
            const body = JSON.stringify({
                accountName: credentials.username,
                password: credentials.password,
                rememberMe: true
            });
            const loginResponse = yield this.$httpClient.httpRequest({
                url: loginUrl,
                method: "POST",
                body,
                headers
            });
            this.$applePortalCookieService.updateUserSessionCookie(loginResponse.headers["set-cookie"]);
        });
    }
    getLoginConfig() {
        return __awaiter(this, void 0, void 0, function* () {
            let config = null;
            try {
                const response = yield this.$httpClient.httpRequest({ url: this.loginConfigEndpoint, method: "GET" });
                config = JSON.parse(response.body);
            }
            catch (err) {
                this.$logger.trace(`Error while executing request to ${this.loginConfigEndpoint}. More info: ${err}`);
            }
            return config || this.defaultLoginConfig;
        });
    }
    handleTwoFactorAuthentication(scnt, xAppleIdSessionId, authServiceKey) {
        return __awaiter(this, void 0, void 0, function* () {
            const headers = {
                'scnt': scnt,
                'X-Apple-Id-Session-Id': xAppleIdSessionId,
                'X-Apple-Widget-Key': authServiceKey,
                'Accept': 'application/json'
            };
            const authResponse = yield this.$httpClient.httpRequest({
                url: "https://idmsa.apple.com/appleauth/auth",
                method: "GET",
                headers
            });
            const data = JSON.parse(authResponse.body);
            if (data.trustedPhoneNumbers && data.trustedPhoneNumbers.length) {
                const parsedAuthResponse = JSON.parse(authResponse.body);
                const token = yield this.$prompter.getString(`Please enter the ${parsedAuthResponse.securityCode.length} digit code`, { allowEmpty: false });
                yield this.$httpClient.httpRequest({
                    url: `https://idmsa.apple.com/appleauth/auth/verify/trusteddevice/securitycode`,
                    method: "POST",
                    body: JSON.stringify({
                        securityCode: {
                            code: token.toString()
                        }
                    }),
                    headers: Object.assign({}, headers, { 'Content-Type': "application/json" })
                });
                const authTrustResponse = yield this.$httpClient.httpRequest({
                    url: "https://idmsa.apple.com/appleauth/auth/2sv/trust",
                    method: "GET",
                    headers
                });
                this.$applePortalCookieService.updateUserSessionCookie(authTrustResponse.headers["set-cookie"]);
            }
            else {
                this.$errors.failWithoutHelp(`Although response from Apple indicated activated Two-step Verification or Two-factor Authentication, NativeScript CLI don't know how to handle this response: ${data}`);
            }
        });
    }
}
exports.ApplePortalSessionService = ApplePortalSessionService;
$injector.register("applePortalSessionService", ApplePortalSessionService);
