"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateArtifacts = exports.getNewConstraint = void 0;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const logger_1 = require("../../../../logger");
const p = tslib_1.__importStar(require("../../../../util/promises"));
const regex_1 = require("../../../../util/regex");
const datasource_1 = require("../../../datasource");
const terraform_provider_1 = require("../../../datasource/terraform-provider");
const versioning_1 = require("../../../versioning");
const util_1 = require("../util");
const hash_1 = require("./hash");
const util_2 = require("./util");
async function updateAllLocks(locks) {
    const updates = await p.map(locks, async (lock) => {
        const updateConfig = {
            versioning: 'hashicorp',
            datasource: 'terraform-provider',
            packageName: lock.packageName,
        };
        const { releases } = (await (0, datasource_1.getPkgReleases)(updateConfig)) ?? {};
        if (!releases) {
            return null;
        }
        const versioning = (0, versioning_1.get)(updateConfig.versioning);
        const versionsList = releases.map((release) => release.version);
        const newVersion = versioning.getSatisfyingVersion(versionsList, lock.constraints);
        // if the new version is the same as the last, signal that no update is needed
        if (!newVersion || newVersion === lock.version) {
            return null;
        }
        const update = {
            newVersion,
            newConstraint: lock.constraints,
            newHashes: (await hash_1.TerraformProviderHash.createHashes(lock.registryUrl, lock.packageName, newVersion)) ?? [],
            ...lock,
        };
        return update;
    }, { concurrency: 4 });
    return updates.filter(is_1.default.truthy);
}
function getNewConstraint(dep, oldConstraint) {
    const { currentValue, currentVersion, newValue: rawNewValue, newVersion, packageName, } = dep;
    const newValue = (0, util_2.massageNewValue)(rawNewValue);
    if (oldConstraint && currentValue && newValue && currentValue === newValue) {
        logger_1.logger.debug(`Leaving constraints "${oldConstraint}" unchanged for "${packageName}" as current and new values are the same`);
        return oldConstraint;
    }
    if (oldConstraint &&
        currentValue &&
        newValue &&
        oldConstraint.includes(currentValue)) {
        logger_1.logger.debug(`Updating constraint "${oldConstraint}" to replace "${currentValue}" with "${newValue}" for "${packageName}"`);
        //remove surplus .0 version
        return oldConstraint.replace((0, regex_1.regEx)(`(,\\s|^)${(0, regex_1.escapeRegExp)(currentValue)}(\\.0)*`), `$1${newValue}`);
    }
    if (oldConstraint &&
        currentVersion &&
        newVersion &&
        oldConstraint.includes(currentVersion)) {
        logger_1.logger.debug(`Updating constraint "${oldConstraint}" to replace "${currentVersion}" with "${newVersion}" for "${packageName}"`);
        return oldConstraint.replace(currentVersion, newVersion);
    }
    if ((0, util_2.isPinnedVersion)(newValue)) {
        logger_1.logger.debug(`Pinning constraint for "${packageName}" to "${newVersion}"`);
        return newVersion;
    }
    logger_1.logger.debug(`Could not detect constraint to update for "${packageName}" so setting to newValue "${newValue}"`);
    return newValue;
}
exports.getNewConstraint = getNewConstraint;
async function updateArtifacts({ packageFileName, updatedDeps, config, }) {
    logger_1.logger.debug(`terraform.updateArtifacts(${packageFileName})`);
    const lockFilePath = await (0, util_2.findLockFile)(packageFileName);
    if (!lockFilePath) {
        logger_1.logger.debug('No .terraform.lock.hcl found');
        return null;
    }
    try {
        const lockFileContent = await (0, util_2.readLockFile)(lockFilePath);
        if (!lockFileContent) {
            logger_1.logger.debug('No .terraform.lock.hcl found');
            return null;
        }
        const locks = (0, util_2.extractLocks)(lockFileContent);
        if (!locks) {
            logger_1.logger.debug('No Locks in .terraform.lock.hcl found');
            return null;
        }
        const updates = [];
        if (config.updateType === 'lockFileMaintenance') {
            // update all locks in the file during maintenance --> only update version in constraints
            const maintenanceUpdates = await updateAllLocks(locks);
            updates.push(...maintenanceUpdates);
        }
        else {
            const providerDeps = updatedDeps.filter((dep) => 
            // TODO #22198
            ['provider', 'required_provider'].includes(dep.depType));
            for (const dep of providerDeps) {
                (0, util_1.massageProviderLookupName)(dep);
                const { registryUrls, newVersion, packageName } = dep;
                const registryUrl = registryUrls
                    ? registryUrls[0]
                    : terraform_provider_1.TerraformProviderDatasource.defaultRegistryUrls[0];
                const updateLock = locks.find((value) => value.packageName === packageName);
                // istanbul ignore if: needs test
                if (!updateLock) {
                    continue;
                }
                const newConstraint = getNewConstraint(dep, updateLock.constraints);
                const update = {
                    // TODO #22198
                    newVersion: newVersion,
                    newConstraint: newConstraint,
                    newHashes: (await hash_1.TerraformProviderHash.createHashes(registryUrl, updateLock.packageName, newVersion)) ?? /* istanbul ignore next: needs test */ [],
                    ...updateLock,
                };
                updates.push(update);
            }
        }
        // if no updates have been found or there are failed hashes abort
        if (updates.length === 0 ||
            updates.some((value) => !value.newHashes?.length)) {
            return null;
        }
        const res = (0, util_2.writeLockUpdates)(updates, lockFilePath, lockFileContent);
        return [res];
    }
    catch (err) {
        /* istanbul ignore next */
        return [
            {
                artifactError: {
                    lockFile: lockFilePath,
                    stderr: err.message,
                },
            },
        ];
    }
}
exports.updateArtifacts = updateArtifacts;
//# sourceMappingURL=index.js.map