package com.atlassian.bitbucket.internal.branch.automerge;

import com.atlassian.bitbucket.internal.branch.automerge.result.MergeContinue;
import com.atlassian.bitbucket.internal.branch.automerge.result.MergeResult;
import com.atlassian.bitbucket.internal.branch.automerge.result.MergeStopped;
import com.atlassian.bitbucket.internal.branch.automerge.result.OpenPullRequestReason;
import com.atlassian.bitbucket.pull.*;
import com.atlassian.bitbucket.repository.Branch;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageUtils;
import com.google.common.collect.Iterables;
import org.springframework.core.annotation.Order;

@Order(1)
public class NoOpenPullRequests implements BranchProcessor {

    private final PullRequestService pullRequestService;

    public NoOpenPullRequests(PullRequestService pullRequestService) {
        this.pullRequestService = pullRequestService;
    }

    @Override
    public MergeResult process(MergeInstruction mergeInstruction) {
        PullRequest pullRequest = findByBranches(mergeInstruction);

        return pullRequest == null ?
                new MergeContinue() :
                new MergeStopped(new OpenPullRequestReason(pullRequest));
    }

    private PullRequest findByBranches(MergeInstruction mergeInstruction) {
        Repository repository = mergeInstruction.getRepository();
        Branch source = mergeInstruction.getSource();
        Branch destination = mergeInstruction.getDestination();

        //Only a single pull request is allowed to be open between any pair of branches, so searching by both
        //fromRefId and toRefId should return a single pull request or none at all
        PullRequestSearchRequest searchRequest = new PullRequestSearchRequest.Builder()
                .fromRefId(source.getId())
                .fromRepositoryId(repository.getId())
                .order(PullRequestOrder.OLDEST)
                .state(PullRequestState.OPEN)
                .toRefId(destination.getId())
                .toRepositoryId(repository.getId())
                .withProperties(false)
                .build();
        Page<PullRequest> page = pullRequestService.search(searchRequest, PageUtils.newRequest(0, 1));

        return Iterables.getOnlyElement(page.getValues(), null);
    }
}
