"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPrHourlyRemaining = getPrHourlyRemaining;
exports.getConcurrentPrsRemaining = getConcurrentPrsRemaining;
exports.getPrsRemaining = getPrsRemaining;
exports.getConcurrentBranchesRemaining = getConcurrentBranchesRemaining;
exports.getBranchesRemaining = getBranchesRemaining;
const luxon_1 = require("luxon");
const logger_1 = require("../../../logger");
const platform_1 = require("../../../modules/platform");
const scm_1 = require("../../../modules/platform/scm");
const external_host_error_1 = require("../../../types/errors/external-host-error");
async function getPrHourlyRemaining(config) {
    if (config.prHourlyLimit) {
        try {
            logger_1.logger.debug('Calculating hourly PRs remaining');
            const prList = await platform_1.platform.getPrList();
            const currentHourStart = luxon_1.DateTime.local().startOf('hour');
            logger_1.logger.debug(`currentHourStart=${String(currentHourStart)}`);
            const soFarThisHour = prList.filter((pr) => pr.sourceBranch !== config.onboardingBranch &&
                pr.sourceBranch.startsWith(config.branchPrefix) &&
                luxon_1.DateTime.fromISO(pr.createdAt) > currentHourStart);
            const prsRemaining = Math.max(0, config.prHourlyLimit - soFarThisHour.length);
            logger_1.logger.debug(`PR hourly limit remaining: ${prsRemaining}`);
            return prsRemaining;
        }
        catch (err) {
            // istanbul ignore if
            if (err instanceof external_host_error_1.ExternalHostError) {
                throw err;
            }
            logger_1.logger.error({ err }, 'Error checking PRs created per hour');
            return config.prHourlyLimit;
        }
    }
    return Number.MAX_SAFE_INTEGER;
}
async function getConcurrentPrsRemaining(config, branches) {
    if (config.prConcurrentLimit) {
        logger_1.logger.debug(`Calculating prConcurrentLimit (${config.prConcurrentLimit})`);
        try {
            const openPrs = [];
            for (const { branchName } of branches) {
                try {
                    const pr = await platform_1.platform.getBranchPr(branchName, config.baseBranch);
                    if (pr &&
                        pr.sourceBranch !== config.onboardingBranch &&
                        pr.state === 'open') {
                        openPrs.push(pr);
                    }
                }
                catch (err) {
                    // istanbul ignore if
                    if (err instanceof external_host_error_1.ExternalHostError) {
                        throw err;
                    }
                    else {
                        // no-op
                    }
                }
            }
            logger_1.logger.debug(`${openPrs.length} PRs are currently open`);
            const concurrentRemaining = Math.max(0, config.prConcurrentLimit - openPrs.length);
            logger_1.logger.debug(`PR concurrent limit remaining: ${concurrentRemaining}`);
            return concurrentRemaining;
        }
        catch (err) /* istanbul ignore next */ {
            logger_1.logger.error({ err }, 'Error checking concurrent PRs');
            return config.prConcurrentLimit;
        }
    }
    return Number.MAX_SAFE_INTEGER;
}
async function getPrsRemaining(config, branches) {
    const hourlyRemaining = await getPrHourlyRemaining(config);
    const concurrentRemaining = await getConcurrentPrsRemaining(config, branches);
    return Math.min(hourlyRemaining, concurrentRemaining);
}
async function getConcurrentBranchesRemaining(config, branches) {
    const { branchConcurrentLimit, prConcurrentLimit } = config;
    const limit = typeof branchConcurrentLimit === 'number'
        ? branchConcurrentLimit
        : prConcurrentLimit;
    if (typeof limit === 'number' && limit) {
        logger_1.logger.debug(`Calculating branchConcurrentLimit (${limit})`);
        try {
            const existingBranches = [];
            for (const branch of branches) {
                if (await scm_1.scm.branchExists(branch.branchName)) {
                    existingBranches.push(branch.branchName);
                }
            }
            const existingCount = existingBranches.length;
            logger_1.logger.debug(`${existingCount} already existing branches found: ${existingBranches.join()}`);
            const concurrentRemaining = Math.max(0, limit - existingCount);
            logger_1.logger.debug(`Branch concurrent limit remaining: ${concurrentRemaining}`);
            return concurrentRemaining;
        }
        catch (err) {
            // TODO: #22198 should never throw
            logger_1.logger.error({ err }, 'Error checking concurrent branches');
            return limit;
        }
    }
    return Number.MAX_SAFE_INTEGER;
}
async function getBranchesRemaining(config, branches) {
    const hourlyRemaining = await getPrHourlyRemaining(config);
    const concurrentRemaining = await getConcurrentBranchesRemaining(config, branches);
    return Math.min(hourlyRemaining, concurrentRemaining);
}
//# sourceMappingURL=limits.js.map