package com.atlassian.stash.internal.build.hook;

import com.atlassian.bitbucket.build.BuildSummary;
import com.atlassian.bitbucket.build.BuildStatusService;
import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.pull.PullRequest;
import com.atlassian.bitbucket.pull.PullRequestRef;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.scm.pull.MergeRequest;
import com.atlassian.bitbucket.scm.pull.MergeRequestCheck;

import javax.annotation.Nonnull;

/**
 * Vetoes any pull request that does not have enough builds.
 */
public class RequiredBuildsMergeCheck implements MergeRequestCheck {

    private final BuildStatusService buildStatusService;
    private final I18nService i18nService;
    private final RequiredBuildsHelper helper;

    public RequiredBuildsMergeCheck(BuildStatusService buildStatusService, I18nService i18nService,
                                    RequiredBuildsHelper helper) {
        this.buildStatusService = buildStatusService;
        this.i18nService = i18nService;
        this.helper = helper;
    }

    @Override
    public void check(@Nonnull MergeRequest mergeRequest) {
        PullRequest pullRequest = mergeRequest.getPullRequest();
        Repository repository = pullRequest.getToRef().getRepository();
        int requiredCount = helper.getRequiredSuccessfulBuildsCount(repository);

        if (requiredCount <= 0) {
            return;
        }

        BuildSummary stats = getBuildStats(pullRequest.getFromRef());
        String vetoMessage = null;
        if (stats.getFailedCount() > 0) {
            vetoMessage = i18nService.getMessage("bitbucket.build.required.count.veto.failed.message");
        } else if (stats.getInProgressCount() > 0) {
            vetoMessage = i18nService.getMessage("bitbucket.build.required.count.veto.inprogress.message");
        }

        // If we need more builds before merging, tell the user how many more successful builds they need.
        int needed = requiredCount - (stats.getSuccessfulCount() + stats.getFailedCount() + stats.getInProgressCount());
        if (needed > 0) {
            String neededMessage = i18nService.getMessage("bitbucket.build.required.count.veto.message", requiredCount);
            if (vetoMessage == null) {
                vetoMessage = neededMessage;
            } else {
                vetoMessage = vetoMessage + " " + neededMessage;
            }
        }
        if (vetoMessage != null) {
            veto(mergeRequest, vetoMessage);
        }
    }

    private BuildSummary getBuildStats(PullRequestRef fromRef) {
        String commitHash = fromRef.getLatestCommit();
        return buildStatusService.getSummary(commitHash);
    }

    private void veto(MergeRequest mergeRequest, String errorMessage) {
        mergeRequest.veto(i18nService.getMessage("bitbucket.build.required.count.veto.short.message"), errorMessage);
    }

}