"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BitbucketPrCache = void 0;
const tslib_1 = require("tslib");
const dequal_1 = require("dequal");
const luxon_1 = require("luxon");
const logger_1 = require("../../../logger");
const memCache = tslib_1.__importStar(require("../../../util/cache/memory"));
const repository_1 = require("../../../util/cache/repository");
const clone_1 = require("../../../util/clone");
const repository_http_cache_provider_1 = require("../../../util/http/cache/repository-http-cache-provider");
const utils_1 = require("./utils");
class BitbucketPrCache {
    repo;
    author;
    cache;
    constructor(repo, author) {
        this.repo = repo;
        this.author = author;
        const repoCache = (0, repository_1.getCache)();
        repoCache.platform ??= {};
        repoCache.platform.bitbucket ??= {};
        let pullRequestCache = repoCache.platform.bitbucket.pullRequestsCache;
        if (!pullRequestCache) {
            logger_1.logger.debug('Initializing new PR cache at repository cache');
            pullRequestCache = {
                items: {},
                updated_on: null,
                author,
            };
        }
        else if (pullRequestCache.author !== author) {
            logger_1.logger.debug('Resetting PR cache because authors do not match');
            pullRequestCache = {
                items: {},
                updated_on: null,
                author,
            };
        }
        repoCache.platform.bitbucket.pullRequestsCache = pullRequestCache;
        this.cache = pullRequestCache;
    }
    static async init(http, repo, author) {
        const res = new BitbucketPrCache(repo, author);
        const isSynced = memCache.get('bitbucket-pr-cache-synced');
        if (!isSynced) {
            await res.sync(http);
            memCache.set('bitbucket-pr-cache-synced', true);
        }
        return res;
    }
    getPrs() {
        return Object.values(this.cache.items);
    }
    static async getPrs(http, repo, author) {
        const prCache = await BitbucketPrCache.init(http, repo, author);
        return prCache.getPrs();
    }
    addPr(pr) {
        logger_1.logger.debug(`Adding PR #${pr.number} to the PR cache`);
        this.cache.items[pr.number] = pr;
    }
    static async addPr(http, repo, author, item) {
        const prCache = await BitbucketPrCache.init(http, repo, author);
        prCache.addPr(item);
    }
    reconcile(rawItems) {
        const { items: oldItems } = this.cache;
        let { updated_on } = this.cache;
        for (const rawItem of rawItems) {
            const id = rawItem.id;
            const oldItem = oldItems[id];
            const newItem = (0, utils_1.prInfo)(rawItem);
            const itemNewTime = luxon_1.DateTime.fromISO(rawItem.updated_on);
            if (!(0, dequal_1.dequal)(oldItem, newItem)) {
                oldItems[id] = newItem;
            }
            const cacheOldTime = updated_on ? luxon_1.DateTime.fromISO(updated_on) : null;
            if (!cacheOldTime || itemNewTime > cacheOldTime) {
                updated_on = rawItem.updated_on;
            }
        }
        this.cache.updated_on = updated_on;
    }
    getUrl() {
        const params = new URLSearchParams();
        for (const state of utils_1.prStates.all) {
            params.append('state', state);
        }
        params.append('fields', utils_1.prFieldsFilter);
        const q = [];
        if (this.author) {
            q.push(`author.uuid = "${this.author}"`);
        }
        if (this.cache.updated_on) {
            q.push(`updated_on > "${this.cache.updated_on}"`);
        }
        params.append('q', q.join(' AND '));
        const query = params.toString();
        return `/2.0/repositories/${this.repo}/pullrequests?${query}`;
    }
    async sync(http) {
        logger_1.logger.debug('Syncing PR list');
        const url = this.getUrl();
        const opts = {
            paginate: true,
            pagelen: 50,
            cacheProvider: repository_http_cache_provider_1.repoCacheProvider,
        };
        const res = await http.getJson(url, opts);
        const items = res.body.values;
        logger_1.logger.debug(`Fetched ${items.length} PRs to sync with cache`);
        const oldCache = (0, clone_1.clone)(this.cache.items);
        this.reconcile(items);
        logger_1.logger.debug(`Total PRs cached: ${Object.values(this.cache.items).length}`);
        logger_1.logger.trace({
            items,
            oldCache,
            newCache: this.cache.items,
        }, `PR cache sync finished`);
        return this;
    }
}
exports.BitbucketPrCache = BitbucketPrCache;
//# sourceMappingURL=pr-cache.js.map