import { map } from 'rambda';
import { inDateRange } from './helpers.js';
import { RepositoryModel } from './mongoose-models/RepositoryModel.js';
import { normalizeBranchName } from '../utils.js';
import { fromContext } from './utils.js';
export const getRepositories = (collectionName, project) => RepositoryModel.find({ collectionName, 'project.name': project }).lean();
export const getRepoIdsAndNames = async ({ collectionName, project, }) => RepositoryModel.find({ collectionName, 'project.name': project }, { _id: 0, id: 1, name: 1 }).lean();
export const getRepoCount = (collectionName, project) => RepositoryModel.countDocuments({ collectionName, 'project.name': project }).exec();
export const repoDefaultBranch = async (collectionName, project, repositoryId) => {
    const repoBranch = await RepositoryModel.findOne({
        collectionName,
        'project.name': project,
        'id': repositoryId,
    }, {
        defaultBranch: 1,
    });
    return (repoBranch === null || repoBranch === void 0 ? void 0 : repoBranch.defaultBranch)
        ? normalizeBranchName(repoBranch.defaultBranch)
        : undefined;
};
export const getAllRepoDefaultBranchIDs = async (collectionName, project, repoIds) => {
    const repoDefaultBranches = await RepositoryModel.aggregate([
        {
            $match: {
                collectionName,
                'project.name': project,
                'defaultBranch': { $exists: true },
                ...(repoIds ? { id: { $in: repoIds } } : {}),
            },
        },
        {
            $addFields: {
                defaultBranch: {
                    $replaceAll: {
                        input: '$defaultBranch',
                        find: 'refs/heads/',
                        replacement: '',
                    },
                },
            },
        },
        {
            $lookup: {
                from: 'branches',
                let: {
                    id: '$id',
                    defaultBranch: '$defaultBranch',
                },
                pipeline: [
                    {
                        $match: {
                            collectionName,
                            project,
                            $expr: {
                                $and: [
                                    { $eq: ['$repositoryId', '$$id'] },
                                    { $eq: ['$name', '$$defaultBranch'] },
                                ],
                            },
                        },
                    },
                ],
                as: 'result',
            },
        },
        {
            $project: {
                _id: 0,
                repositoryId: '$id',
                defaultBranchName: {
                    $arrayElemAt: ['$result.name', 0],
                },
                defaultBranchId: {
                    $arrayElemAt: ['$result._id', 0],
                },
            },
        },
        {
            $match: {
                defaultBranchId: {
                    $exists: true,
                },
            },
        },
    ]);
    return repoDefaultBranches.map(repo => repo.defaultBranchId);
};
export const formatRepoUrlForUI = (repoUrl) => repoUrl.replace('/_apis/git/repositories/', '/_git/');
export const getDefaultBranchAndNameForRepoIds = (queryContext, repositoryIds) => {
    const { collectionName, project } = fromContext(queryContext);
    return RepositoryModel.find({ collectionName, 'project.name': project, 'id': { $in: repositoryIds } }, { _id: 0, id: 1, name: 1, defaultBranch: 1, url: 1 })
        .lean()
        .then(map(repo => ({
        id: repo.id,
        name: repo.name,
        defaultBranch: repo.defaultBranch,
        url: formatRepoUrlForUI(repo.url),
    })));
};
export const getReposSortedByBuildCount = async (queryContext, repositoryIds, sortOrder, pageSize, pageNumber) => {
    const { collectionName, project, startDate, endDate } = fromContext(queryContext);
    return RepositoryModel.aggregate([
        {
            $match: {
                collectionName,
                'project.name': project,
                'id': { $in: repositoryIds },
            },
        },
        {
            $lookup: {
                from: 'builds',
                let: {
                    repositoryId: '$id',
                },
                pipeline: [
                    {
                        $match: {
                            collectionName,
                            project,
                            $expr: {
                                $and: [
                                    { $eq: ['$repository.id', '$$repositoryId'] },
                                    { $gte: ['$finishTime', startDate] },
                                    { $lte: ['$finishTime', endDate] },
                                ],
                            },
                        },
                    },
                ],
                as: 'builds',
            },
        },
        {
            $project: {
                _id: 0,
                repositoryId: '$id',
                count: { $size: '$builds' },
            },
        },
        { $sort: { count: sortOrder === 'asc' ? 1 : -1, repositoryId: -1 } },
        { $skip: pageSize * pageNumber },
        { $limit: pageSize },
    ]).exec();
};
export const getReposSortedByBranchesCount = async (queryContext, repositoryIds, sortOrder, pageSize, pageNumber) => {
    const { collectionName, project } = fromContext(queryContext);
    return RepositoryModel.aggregate([
        {
            $match: {
                collectionName,
                'project.name': project,
                'id': { $in: repositoryIds },
            },
        },
        {
            $lookup: {
                from: 'branches',
                let: {
                    repositoryId: '$id',
                },
                pipeline: [
                    {
                        $match: {
                            collectionName,
                            project,
                            $expr: {
                                $eq: ['$repositoryId', '$$repositoryId'],
                            },
                        },
                    },
                ],
                as: 'branches',
            },
        },
        {
            $project: {
                _id: 0,
                repositoryId: '$id',
                count: { $size: '$branches' },
            },
        },
        { $sort: { count: sortOrder === 'asc' ? 1 : -1, repositoryId: -1 } },
        { $skip: pageSize * pageNumber },
        { $limit: pageSize },
    ]).exec();
};
export const getReposSortedByCommitsCount = (queryContext, repositoryIds, sortOrder, pageSize, pageNumber) => {
    const { collectionName, project, startDate, endDate } = fromContext(queryContext);
    return RepositoryModel.aggregate([
        {
            $match: {
                collectionName,
                'project.name': project,
                'id': { $in: repositoryIds },
            },
        },
        {
            $lookup: {
                from: 'commits',
                let: {
                    repositoryId: '$id',
                },
                pipeline: [
                    {
                        $match: {
                            collectionName,
                            project,
                            '$expr': {
                                $eq: ['$repositoryId', '$$repositoryId'],
                            },
                            'author.date': inDateRange(startDate, endDate),
                        },
                    },
                ],
                as: 'commits',
            },
        },
        {
            $project: {
                _id: 0,
                repositoryId: '$id',
                count: { $size: '$commits' },
            },
        },
        { $sort: { count: sortOrder === 'asc' ? 1 : -1, repositoryId: -1 } },
        { $skip: pageSize * pageNumber },
        { $limit: pageSize },
    ]).exec();
};
export const getReposSortedByPullRequestsCount = (queryContext, repositoryIds, sortOrder, pageSize, pageNumber) => {
    const { collectionName, project, startDate, endDate } = fromContext(queryContext);
    return RepositoryModel.aggregate([
        {
            $match: {
                collectionName,
                'project.name': project,
                'id': { $in: repositoryIds },
            },
        },
        {
            $lookup: {
                from: 'pullrequests',
                let: {
                    repositoryId: '$id',
                },
                pipeline: [
                    {
                        $match: {
                            collectionName,
                            project,
                            $expr: {
                                $and: [
                                    { $eq: ['$repositoryId', '$$repositoryId'] },
                                    {
                                        $or: [
                                            { $eq: ['$status', 'active'] },
                                            {
                                                $and: [
                                                    { $in: ['$status', ['abandoned', 'completed']] },
                                                    { $gte: ['$closedDate', startDate] },
                                                    { $lt: ['$closedDate', endDate] },
                                                ],
                                            },
                                        ],
                                    },
                                ],
                            },
                        },
                    },
                ],
                as: 'pullrequests',
            },
        },
        {
            $project: {
                _id: 0,
                repositoryId: '$id',
                count: { $size: '$pullrequests' },
                name: 1,
            },
        },
        { $sort: { count: sortOrder === 'asc' ? 1 : -1, repositoryId: -1 } },
        { $skip: pageSize * pageNumber },
        { $limit: pageSize },
    ]).exec();
};
