"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    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) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
    return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.UploadServiceHeaders = void 0;
exports.getToken = getToken;
exports.getOrganizationId = getOrganizationId;
exports.getPublishProfileId = getPublishProfileId;
exports.getAppVersions = getAppVersions;
exports.getLatestAppVersionId = getLatestAppVersionId;
exports.getReleaseCandidateVersionId = getReleaseCandidateVersionId;
exports.markReleaseCandidate = markReleaseCandidate;
exports.getActivePublishCountForProfile = getActivePublishCountForProfile;
exports.uploadPublishApp = uploadPublishApp;
exports.checkTaskStatus = checkTaskStatus;
exports.getPublishId = getPublishId;
exports.startPublish = startPublish;
exports.pollPublishStatus = pollPublishStatus;
var tl = require("azure-pipelines-task-lib/task");
var axios_1 = require("axios");
var fs = require("fs");
var FormData = require("form-data");
var path = require("path");
var FLOW_STEP_STATUS = {
    0: "Success", 1: "Failed", 2: "Cancelled", 3: "Timeout",
    90: "Waiting", 91: "Running", 92: "Completing", 99: "Unknown",
    100: "Skipped", 200: "Not Started", 201: "Stopped",
    202: "In Progress", 203: "Awaiting Response",
};
var TERMINAL_STEP_STATUSES = new Set([0, 1, 2, 3, 100, 201]);
var ACTIVE_STEP_STATUSES = new Set([91, 92, 202]);
function stepStatusName(status) {
    var _a;
    return (_a = FLOW_STEP_STATUS[status]) !== null && _a !== void 0 ? _a : "Unknown (".concat(status, ")");
}
// Emoji icons carry green/red semantics without ANSI codes, so they render in CI logs.
function stepIcon(status) {
    switch (status) {
        case 0: return "✅";
        case 1: return "❌";
        case 2: return "🚫";
        case 3: return "⌛";
        case 100: return "⏭️";
        case 201: return "⏹️";
        case 203: return "⏸️";
        default: return "▶️";
    }
}
function run() {
    return __awaiter(this, void 0, void 0, function () {
        var personalAPIToken, authEndpoint, apiEndpoint, platform, publishProfile, upload, publish, appPath, subOrganizationName, validExtensions, fileExtension, appcircleApi, loginResponse, subOrganizationId, subLoginResponse, publishProfileId, active, appVersionId, uploadResponse, ok, publishId, success, err_1;
        var _a, _b;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    _c.trys.push([0, 20, , 21]);
                    personalAPIToken = tl.getInputRequired("personalAPIToken");
                    authEndpoint = (_a = tl.getInput("authEndpoint")) !== null && _a !== void 0 ? _a : "https://auth.appcircle.io";
                    apiEndpoint = (_b = tl.getInput("apiEndpoint")) !== null && _b !== void 0 ? _b : "https://api.appcircle.io";
                    platform = (tl.getInputRequired("platform") || "").toLowerCase();
                    publishProfile = tl.getInputRequired("publishProfile");
                    upload = tl.getBoolInput("upload");
                    publish = tl.getBoolInput("publish");
                    appPath = tl.getInput("appPath");
                    subOrganizationName = tl.getInput("subOrganizationName");
                    // --- Validation ---
                    if (!upload && !publish) {
                        tl.setResult(tl.TaskResult.Failed, "Nothing to do: enable 'upload' and/or 'publish'.");
                        return [2 /*return*/];
                    }
                    if (platform !== "ios" && platform !== "android") {
                        tl.setResult(tl.TaskResult.Failed, "Invalid platform: ".concat(platform, ". Use 'ios' or 'android'."));
                        return [2 /*return*/];
                    }
                    if (upload) {
                        if (!appPath) {
                            tl.setResult(tl.TaskResult.Failed, "'appPath' is required when 'upload' is enabled.");
                            return [2 /*return*/];
                        }
                        validExtensions = [".apk", ".aab", ".ipa"];
                        fileExtension = appPath.slice(appPath.lastIndexOf(".")).toLowerCase();
                        if (!validExtensions.includes(fileExtension)) {
                            tl.setResult(tl.TaskResult.Failed, "Invalid file extension: ".concat(appPath, ". For Android, use .apk or .aab. For iOS, use .ipa."));
                            return [2 /*return*/];
                        }
                    }
                    appcircleApi = axios_1.default.create({ baseURL: new URL(apiEndpoint).toString() });
                    return [4 /*yield*/, getToken(personalAPIToken, authEndpoint)];
                case 1:
                    loginResponse = _c.sent();
                    UploadServiceHeaders.token = loginResponse.access_token;
                    console.log("Logged in to Appcircle successfully");
                    if (!subOrganizationName) return [3 /*break*/, 4];
                    return [4 /*yield*/, getOrganizationId(appcircleApi, subOrganizationName)];
                case 2:
                    subOrganizationId = _c.sent();
                    return [4 /*yield*/, getToken(personalAPIToken, authEndpoint, subOrganizationId)];
                case 3:
                    subLoginResponse = _c.sent();
                    UploadServiceHeaders.token = subLoginResponse.access_token;
                    console.log("Switched to sub-organization: ".concat(subOrganizationName));
                    _c.label = 4;
                case 4: return [4 /*yield*/, getPublishProfileId(appcircleApi, platform, publishProfile)];
                case 5:
                    publishProfileId = _c.sent();
                    if (!publish) return [3 /*break*/, 7];
                    return [4 /*yield*/, getActivePublishCountForProfile(appcircleApi, publishProfileId)];
                case 6:
                    active = _c.sent();
                    if (active > 0) {
                        tl.setResult(tl.TaskResult.Failed, "A publish is already in progress for profile '".concat(publishProfile, "'. Not starting a new one."));
                        return [2 /*return*/];
                    }
                    _c.label = 7;
                case 7:
                    appVersionId = void 0;
                    if (!upload) return [3 /*break*/, 11];
                    return [4 /*yield*/, uploadPublishApp(appcircleApi, platform, publishProfileId, appPath)];
                case 8:
                    uploadResponse = _c.sent();
                    return [4 /*yield*/, checkTaskStatus(appcircleApi, uploadResponse.taskId)];
                case 9:
                    ok = _c.sent();
                    if (!ok) {
                        tl.setResult(tl.TaskResult.Failed, "".concat(uploadResponse.taskId, " id upload request failed with status Cancelled"));
                        return [2 /*return*/];
                    }
                    return [4 /*yield*/, getLatestAppVersionId(appcircleApi, platform, publishProfileId)];
                case 10:
                    appVersionId = _c.sent();
                    console.log("".concat(appPath, " uploaded to the Appcircle Publish profile '").concat(publishProfile, "' successfully"));
                    _c.label = 11;
                case 11:
                    if (!publish) return [3 /*break*/, 19];
                    if (!(upload && appVersionId)) return [3 /*break*/, 13];
                    return [4 /*yield*/, markReleaseCandidate(appcircleApi, platform, publishProfileId, appVersionId)];
                case 12:
                    _c.sent();
                    console.log("Marked the uploaded version as release candidate.");
                    return [3 /*break*/, 15];
                case 13: return [4 /*yield*/, getReleaseCandidateVersionId(appcircleApi, platform, publishProfileId)];
                case 14:
                    appVersionId = _c.sent();
                    _c.label = 15;
                case 15: return [4 /*yield*/, getPublishId(appcircleApi, platform, publishProfileId, appVersionId)];
                case 16:
                    publishId = _c.sent();
                    return [4 /*yield*/, startPublish(appcircleApi, platform, publishProfileId, publishId)];
                case 17:
                    _c.sent();
                    console.log("Publish flow started for profile '".concat(publishProfile, "'."));
                    return [4 /*yield*/, pollPublishStatus(appcircleApi, platform, publishProfileId, appVersionId)];
                case 18:
                    success = _c.sent();
                    if (!success) {
                        tl.setResult(tl.TaskResult.Failed, "Publish flow failed.");
                        return [2 /*return*/];
                    }
                    _c.label = 19;
                case 19:
                    tl.setResult(tl.TaskResult.Succeeded, "Appcircle Publish action completed successfully.");
                    return [3 /*break*/, 21];
                case 20:
                    err_1 = _c.sent();
                    tl.setResult(tl.TaskResult.Failed, err_1.message);
                    return [3 /*break*/, 21];
                case 21: return [2 /*return*/];
            }
        });
    });
}
run();
/* API */
function getToken(pat, authEndpoint, subOrganizationId) {
    return __awaiter(this, void 0, void 0, function () {
        var params, tokenPath, url, response, error_1;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    params = new URLSearchParams();
                    params.append("pat", pat);
                    tokenPath = subOrganizationId ? "/auth/v2/token" : "/auth/v1/token";
                    if (subOrganizationId) {
                        params.append("subOrganizationId", subOrganizationId);
                    }
                    _a.label = 1;
                case 1:
                    _a.trys.push([1, 3, , 4]);
                    url = new URL(tokenPath, authEndpoint).toString();
                    return [4 /*yield*/, axios_1.default.post(url, params.toString(), {
                            headers: {
                                accept: "application/json",
                                "content-type": "application/x-www-form-urlencoded",
                            },
                        })];
                case 2:
                    response = _a.sent();
                    return [2 /*return*/, response.data];
                case 3:
                    error_1 = _a.sent();
                    if (axios_1.default.isAxiosError(error_1)) {
                        console.error("Axios error:", error_1.message);
                        if (error_1.response) {
                            console.error("Response status:", error_1.response.status);
                        }
                    }
                    else {
                        console.error("Unexpected error:", error_1);
                    }
                    throw error_1;
                case 4: return [2 /*return*/];
            }
        });
    });
}
function getOrganizationId(api, name) {
    return __awaiter(this, void 0, void 0, function () {
        var response, organizations, organization;
        var _a, _b;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0: return [4 /*yield*/, api.get("identity/v1/organizations", {
                        headers: UploadServiceHeaders.getHeaders(),
                    })];
                case 1:
                    response = _c.sent();
                    organizations = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [];
                    organization = organizations.find(function (org) { return org.name === name; });
                    if (!organization) {
                        throw new Error("Sub-organization '".concat(name, "' could not be found or is not accessible with this token."));
                    }
                    return [2 /*return*/, organization.id];
            }
        });
    });
}
var UploadServiceHeaders = /** @class */ (function () {
    function UploadServiceHeaders() {
    }
    UploadServiceHeaders.token = "";
    UploadServiceHeaders.getHeaders = function () {
        var response = {
            accept: "application/json",
            "User-Agent": "Appcircle Azure DevOps Extension",
        };
        response.Authorization = "Bearer ".concat(UploadServiceHeaders.token);
        return response;
    };
    return UploadServiceHeaders;
}());
exports.UploadServiceHeaders = UploadServiceHeaders;
function getPublishProfileId(api, platform, profileName) {
    return __awaiter(this, void 0, void 0, function () {
        var response, profiles, profile;
        var _a, _b;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0: return [4 /*yield*/, api.get("publish/v2/profiles/".concat(platform), {
                        headers: UploadServiceHeaders.getHeaders(),
                    })];
                case 1:
                    response = _c.sent();
                    profiles = Array.isArray(response.data) ? response.data : ((_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : []);
                    profile = profiles.find(function (p) { return p.name === profileName; });
                    if (!profile) {
                        throw new Error("Publish profile '".concat(profileName, "' not found for platform '").concat(platform, "'."));
                    }
                    return [2 /*return*/, profile.id];
            }
        });
    });
}
function getAppVersions(api, platform, publishProfileId) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        var _a, _b;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0: return [4 /*yield*/, api.get("publish/v2/profiles/".concat(platform, "/").concat(publishProfileId, "/app-versions"), { headers: UploadServiceHeaders.getHeaders() })];
                case 1:
                    response = _c.sent();
                    return [2 /*return*/, Array.isArray(response.data) ? response.data : ((_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [])];
            }
        });
    });
}
function getLatestAppVersionId(api, platform, publishProfileId) {
    return __awaiter(this, void 0, void 0, function () {
        var versions;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, getAppVersions(api, platform, publishProfileId)];
                case 1:
                    versions = _a.sent();
                    if (!versions.length) {
                        throw new Error("No app versions found on the publish profile after upload.");
                    }
                    return [2 /*return*/, versions[0].id];
            }
        });
    });
}
function getReleaseCandidateVersionId(api, platform, publishProfileId) {
    return __awaiter(this, void 0, void 0, function () {
        var versions, rc;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, getAppVersions(api, platform, publishProfileId)];
                case 1:
                    versions = _a.sent();
                    rc = versions.find(function (v) { return v.releaseCandidate === true; });
                    if (!rc) {
                        throw new Error("No release candidate app version found on the publish profile. Mark a version as release candidate (or enable upload) before publishing.");
                    }
                    return [2 /*return*/, rc.id];
            }
        });
    });
}
function markReleaseCandidate(api, platform, publishProfileId, appVersionId) {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, api.patch("publish/v2/profiles/".concat(platform, "/").concat(publishProfileId, "/app-versions/").concat(appVersionId, "?action=releaseCandidate"), { ReleaseCandidate: true }, { headers: __assign(__assign({}, UploadServiceHeaders.getHeaders()), { "Content-Type": "application/json" }) })];
                case 1:
                    _a.sent();
                    return [2 /*return*/];
            }
        });
    });
}
function getActivePublishCountForProfile(api, publishProfileId) {
    return __awaiter(this, void 0, void 0, function () {
        var response, items;
        var _a, _b;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0: return [4 /*yield*/, api.get("build/v1/queue/my-dashboard?page=1&size=1000", {
                        headers: UploadServiceHeaders.getHeaders(),
                    })];
                case 1:
                    response = _c.sent();
                    items = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : [];
                    return [2 /*return*/, items.filter(function (p) { return p.publishId != null && p.profileId === publishProfileId; }).length];
            }
        });
    });
}
var RETRYABLE_UPLOAD_STATUSES = new Set([408, 429, 500, 502, 503, 504]);
var RETRYABLE_UPLOAD_CODES = new Set(["ECONNRESET", "ECONNABORTED", "ETIMEDOUT", "EAI_AGAIN"]);
function uploadWithRetry(doUpload_1) {
    return __awaiter(this, arguments, void 0, function (doUpload, maxRetries) {
        var attempt, delay, _loop_1, state_1;
        var _a;
        if (maxRetries === void 0) { maxRetries = 5; }
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    attempt = 0;
                    delay = 1000;
                    _loop_1 = function () {
                        var _c, error_2, status_1, message, retryable, jitter_1;
                        return __generator(this, function (_d) {
                            switch (_d.label) {
                                case 0:
                                    _d.trys.push([0, 2, , 4]);
                                    _c = {};
                                    return [4 /*yield*/, doUpload()];
                                case 1: return [2 /*return*/, (_c.value = _d.sent(), _c)];
                                case 2:
                                    error_2 = _d.sent();
                                    status_1 = (_a = error_2 === null || error_2 === void 0 ? void 0 : error_2.response) === null || _a === void 0 ? void 0 : _a.status;
                                    message = typeof (error_2 === null || error_2 === void 0 ? void 0 : error_2.message) === "string" ? error_2.message.toLowerCase() : "";
                                    retryable = (typeof status_1 === "number" && RETRYABLE_UPLOAD_STATUSES.has(status_1)) ||
                                        (typeof (error_2 === null || error_2 === void 0 ? void 0 : error_2.code) === "string" && RETRYABLE_UPLOAD_CODES.has(error_2.code)) ||
                                        message.includes("socket hang up");
                                    if (!retryable || attempt >= maxRetries) {
                                        throw error_2;
                                    }
                                    attempt++;
                                    jitter_1 = Math.floor(Math.random() * 300);
                                    return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, delay + jitter_1); })];
                                case 3:
                                    _d.sent();
                                    delay *= 2;
                                    return [3 /*break*/, 4];
                                case 4: return [2 /*return*/];
                            }
                        });
                    };
                    _b.label = 1;
                case 1:
                    if (!true) return [3 /*break*/, 3];
                    return [5 /*yield**/, _loop_1()];
                case 2:
                    state_1 = _b.sent();
                    if (typeof state_1 === "object")
                        return [2 /*return*/, state_1.value];
                    return [3 /*break*/, 1];
                case 3: return [2 /*return*/];
            }
        });
    });
}
function uploadPublishApp(api, platform, publishProfileId, app) {
    return __awaiter(this, void 0, void 0, function () {
        var filePath, fileName, fileSize, basePath, uploadInfoResponse, _a, fileId, uploadUrl, configuration, httpMethod, signParameters, commitResponse;
        var _b, _c, _d;
        return __generator(this, function (_e) {
            switch (_e.label) {
                case 0:
                    filePath = app;
                    fileName = path.basename(filePath);
                    fileSize = fs.statSync(filePath).size;
                    basePath = "publish/v1/profiles/".concat(platform, "/").concat(publishProfileId, "/app-versions");
                    console.log("Getting file upload information...");
                    return [4 /*yield*/, api.get(basePath, {
                            params: { action: "uploadInformation", fileName: fileName, fileSize: fileSize },
                            headers: UploadServiceHeaders.getHeaders(),
                        })];
                case 1:
                    uploadInfoResponse = _e.sent();
                    _a = uploadInfoResponse.data, fileId = _a.fileId, uploadUrl = _a.uploadUrl, configuration = _a.configuration;
                    httpMethod = (_c = (_b = configuration === null || configuration === void 0 ? void 0 : configuration.httpMethod) === null || _b === void 0 ? void 0 : _b.toUpperCase()) !== null && _c !== void 0 ? _c : "PUT";
                    signParameters = (_d = configuration === null || configuration === void 0 ? void 0 : configuration.signParameters) !== null && _d !== void 0 ? _d : {};
                    console.log("Uploading file to Appcircle...");
                    if (!(httpMethod === "POST")) return [3 /*break*/, 3];
                    return [4 /*yield*/, uploadWithRetry(function () {
                            // @ts-ignore
                            var data = new FormData();
                            for (var _i = 0, _a = Object.entries(signParameters); _i < _a.length; _i++) {
                                var _b = _a[_i], key = _b[0], value = _b[1];
                                data.append(key, value);
                            }
                            data.append("file", fs.createReadStream(filePath), fileName);
                            return axios_1.default.post(uploadUrl, data, {
                                maxContentLength: Infinity,
                                maxBodyLength: Infinity,
                                headers: __assign({}, data.getHeaders()),
                            });
                        })];
                case 2:
                    _e.sent();
                    return [3 /*break*/, 5];
                case 3: return [4 /*yield*/, uploadWithRetry(function () {
                        return axios_1.default.put(uploadUrl, fs.readFileSync(filePath), {
                            headers: { "Content-Type": "application/octet-stream" },
                            maxContentLength: Infinity,
                            maxBodyLength: Infinity,
                        });
                    })];
                case 4:
                    _e.sent();
                    _e.label = 5;
                case 5:
                    console.log("Committing file upload...");
                    return [4 /*yield*/, api.post(basePath, { fileId: fileId, fileName: fileName }, { params: { action: "commitFileUpload" }, headers: UploadServiceHeaders.getHeaders() })];
                case 6:
                    commitResponse = _e.sent();
                    return [2 /*return*/, commitResponse.data];
            }
        });
    });
}
function checkTaskStatus(api_1, taskId_1) {
    return __awaiter(this, arguments, void 0, function (api, taskId, currentAttempt) {
        var response;
        if (currentAttempt === void 0) { currentAttempt = 0; }
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, api.get("/task/v1/tasks/".concat(taskId), {
                        headers: UploadServiceHeaders.getHeaders(),
                    })];
                case 1:
                    response = _a.sent();
                    if (!((response === null || response === void 0 ? void 0 : response.data.stateValue) == 1 && currentAttempt < 100)) return [3 /*break*/, 3];
                    return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 1000); })];
                case 2:
                    _a.sent();
                    return [2 /*return*/, checkTaskStatus(api, taskId, currentAttempt + 1)];
                case 3:
                    if (response.data.stateValue === 2) {
                        return [2 /*return*/, false];
                    }
                    return [2 /*return*/, true];
            }
        });
    });
}
function getPublishId(api, platform, publishProfileId, appVersionId) {
    return __awaiter(this, void 0, void 0, function () {
        var response, steps, publishId;
        var _a, _b, _c;
        return __generator(this, function (_d) {
            switch (_d.label) {
                case 0: return [4 /*yield*/, api.get("publish/v2/profiles/".concat(platform, "/").concat(publishProfileId, "/app-versions/").concat(appVersionId, "/publish"), { headers: UploadServiceHeaders.getHeaders() })];
                case 1:
                    response = _d.sent();
                    steps = (_b = (_a = response.data) === null || _a === void 0 ? void 0 : _a.steps) !== null && _b !== void 0 ? _b : [];
                    publishId = (_c = steps[0]) === null || _c === void 0 ? void 0 : _c.publishId;
                    if (!publishId) {
                        throw new Error("No publish flow steps found for the app version. Configure a publish flow on the profile first.");
                    }
                    return [2 /*return*/, publishId];
            }
        });
    });
}
function startPublish(api, platform, publishProfileId, publishId) {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, api.post("publish/v2/profiles/".concat(platform, "/").concat(publishProfileId, "/publish/").concat(publishId, "?action=restart"), "{}", { headers: __assign(__assign({}, UploadServiceHeaders.getHeaders()), { "Content-Type": "application/json" }) })];
                case 1:
                    _a.sent();
                    return [2 /*return*/];
            }
        });
    });
}
// Poll the publish status until terminal (0=success, 1=failed, else running),
// logging each step's start / await / terminal once with status icons.
function pollPublishStatus(api_1, platform_1, publishProfileId_1, appVersionId_1) {
    return __awaiter(this, arguments, void 0, function (api, platform, publishProfileId, appVersionId, intervalMs, maxAttempts) {
        var stepState, attempt, response, data, steps, _i, steps_1, step, id, state, status_2, status_3;
        var _a, _b, _c, _d;
        if (intervalMs === void 0) { intervalMs = 5000; }
        if (maxAttempts === void 0) { maxAttempts = 240; }
        return __generator(this, function (_e) {
            switch (_e.label) {
                case 0:
                    stepState = {};
                    attempt = 0;
                    _e.label = 1;
                case 1:
                    if (!(attempt < maxAttempts)) return [3 /*break*/, 5];
                    return [4 /*yield*/, api.get("publish/v1/profiles/".concat(platform, "/").concat(publishProfileId, "/app-versions/").concat(appVersionId, "/publish"), { headers: UploadServiceHeaders.getHeaders() })];
                case 2:
                    response = _e.sent();
                    data = (_a = response.data) !== null && _a !== void 0 ? _a : {};
                    steps = (_b = data.steps) !== null && _b !== void 0 ? _b : [];
                    for (_i = 0, steps_1 = steps; _i < steps_1.length; _i++) {
                        step = steps_1[_i];
                        id = (_c = step.id) !== null && _c !== void 0 ? _c : step.name;
                        if (!id)
                            continue;
                        state = ((_d = stepState[id]) !== null && _d !== void 0 ? _d : (stepState[id] = {}));
                        status_2 = step.status;
                        if (TERMINAL_STEP_STATUSES.has(status_2) && !state.done) {
                            state.done = true;
                            console.log("".concat(stepIcon(status_2), " ").concat(step.name, " \u2014 ").concat(stepStatusName(status_2)));
                        }
                        else if (status_2 === 203 && !state.awaiting && !state.done) {
                            state.awaiting = true;
                            console.log("".concat(stepIcon(status_2), " ").concat(step.name, " \u2014 ").concat(stepStatusName(status_2)));
                        }
                        else if (ACTIVE_STEP_STATUSES.has(status_2) && !state.started && !state.done) {
                            state.started = true;
                            console.log("".concat(stepIcon(status_2), " ").concat(step.name, " \u2014 ").concat(stepStatusName(status_2)));
                        }
                    }
                    status_3 = typeof data.status === "number" ? data.status : 99;
                    if (status_3 === 0) {
                        console.log("Publish completed successfully.");
                        return [2 /*return*/, true];
                    }
                    if (status_3 === 1) {
                        console.log("Publish failed.");
                        return [2 /*return*/, false];
                    }
                    return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, intervalMs); })];
                case 3:
                    _e.sent();
                    _e.label = 4;
                case 4:
                    attempt++;
                    return [3 /*break*/, 1];
                case 5: throw new Error("Publish status polling timed out.");
            }
        });
    });
}
