import { collectionsAndProjects, configForProject, getConfig } from '../config.js';
import { CombinedBranchPoliciesModel, RepoPolicyModel, } from '../models/mongoose-models/RepoPoliciesModel.js';
import azure from '../scraper/network/azure.js';
import { invokeSeries } from '../utils.js';
export const bulkSavePolicies = (collectionName, project) => (policies) => RepoPolicyModel.bulkWrite(
// @ts-expect-error Seems to be a bug with mongoose. See commend below
policies.map(p => {
    const { settings: { scope, ...settings }, ...policy } = p;
    return {
        updateOne: {
            filter: {
                collectionName,
                project,
                repositoryId: scope[0].repositoryId,
                id: policy.id,
            },
            update: {
                $set: {
                    typeId: policy.type.id,
                    createdById: policy.createdBy.id,
                    createdDate: policy.createdDate,
                    isEnabled: policy.isEnabled,
                    isDeleted: policy.isDeleted,
                    isBlocking: policy.isBlocking,
                    refName: 'refName' in scope[0] ? scope[0].refName : undefined,
                    // Type definitions here seems to be a bug with mongoose
                    type: policy.type.displayName,
                    settings,
                },
            },
            upsert: true,
        },
    };
}));
export const refreshCombinedBranchPoliciesView = async () => {
    var _a;
    await CombinedBranchPoliciesModel.collection.drop();
    const results = RepoPolicyModel.aggregate([
        { $match: { refName: { $exists: true }, isDeleted: false } },
        {
            $group: {
                _id: {
                    collectionName: '$collectionName',
                    project: '$project',
                    repositoryId: '$repositoryId',
                    refName: '$refName',
                },
                policies: {
                    $push: {
                        k: '$type',
                        v: {
                            isEnabled: '$isEnabled',
                            isBlocking: '$isBlocking',
                            minimumApproverCount: '$settings.minimumApproverCount',
                            buildDefinitionId: '$settings.buildDefinitionId',
                        },
                    },
                },
            },
        },
        {
            $addFields: {
                policies: { $arrayToObject: '$policies' },
                collectionName: '$_id.collectionName',
                project: '$_id.project',
                repositoryId: '$_id.repositoryId',
                refName: '$_id.refName',
            },
        },
        { $unset: '_id' },
    ]);
    // eslint-disable-next-line no-restricted-syntax
    for await (const match of results) {
        const branchPolicies = (_a = configForProject(match.collectionName, match.project)) === null || _a === void 0 ? void 0 : _a.branchPolicies;
        // eslint-disable-next-line no-continue
        if (!branchPolicies)
            continue;
        const conforms = Object.entries(branchPolicies).every(([p, policyConfig]) => {
            const policyName = p;
            const matchingPolicy = match.policies[policyName];
            if (!matchingPolicy)
                return false;
            const isActive = matchingPolicy.isEnabled === policyConfig.isEnabled &&
                matchingPolicy.isBlocking === policyConfig.isBlocking;
            if (!isActive)
                return false;
            if (policyName === 'Minimum number of reviewers' &&
                'minimumApproverCount' in policyConfig) {
                return ((matchingPolicy.minimumApproverCount || 0) >= policyConfig.minimumApproverCount);
            }
            return true;
        });
        await CombinedBranchPoliciesModel.create({
            ...match,
            conforms,
        });
    }
};
export const getPolicyConfigurations = async () => {
    const { getPolicyConfigurations } = azure(getConfig());
    await invokeSeries(collectionsAndProjects(), ([collection, project]) => {
        return getPolicyConfigurations(collection.name, project.name).then(bulkSavePolicies(collection.name, project.name));
    });
    return refreshCombinedBranchPoliciesView();
};
