package com.atlassian.stash.internal.scm.git.pull;

import com.atlassian.bitbucket.scm.git.GitAgent;
import com.atlassian.bitbucket.scm.git.GitScmConfig;
import com.atlassian.bitbucket.scm.git.command.GitCommandBuilderFactory;
import com.atlassian.bitbucket.scm.git.command.merge.GitNoCommonAncestorException;
import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.stash.internal.scm.git.porcelain.GitPorcelain;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.scm.annotation.Repo;
import org.junit.Test;

import javax.annotation.Resource;

import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;

public class CommonAncestorPullRequestAutoMergeStrategyTest extends AbstractPullRequestGitTest {

    @Resource
    private GitAgent agent;
    @Resource
    private GitCommandBuilderFactory builderFactory;
    @Resource
    private GitScmConfig config;
    @Resource
    private I18nService i18nService;
    @Resource
    private GitPorcelain porcelain;
    @Repo
    private Repository secondaryRepository;
    private CommonAncestorPullRequestAutoMergeStrategy strategy;

    public CommonAncestorPullRequestAutoMergeStrategyTest() {
        super(4L);
    }

    @Override
    public void setup() {
        super.setup();

        strategy = new CommonAncestorPullRequestAutoMergeStrategy(builderFactory, config, i18nService, porcelain);
    }

    @Test
    public void testMerge() throws Exception {
        prepareRefs("branch_with_ignore_conflicts_src", "c927809216a016aee8635896daf7af1fce50f6e1",
                "branch_with_ignore_conflicts_trgt", "74de5497dfca9731e455d60552f9a8906e5dc1ac");

        PullRequestMerge merge = strategy.merge(createMergeRequest(), createRefs());
        assertNotNull(merge);
        assertEquals("3528cf690cb37f6adb85b7bd40cc7a6118d4b598", merge.getHash());
        assertSame(PullRequestMergeType.BASE, merge.getType());
    }

    @Test(expected = GitNoCommonAncestorException.class)
    public void testMergeWithNoCommonAncestor() {
        reset(fromRef);

        when(fromRef.getRepository()).thenReturn(secondaryRepository);

        //Uses the master commits in two different repositories
        prepareRefs("master", "0a943a29376f2336b78312d99e65da17048951db",
                "master", "017caf31eca7c46eb3d1800fcac431cfa7147a01");

        DefaultPullRequestRefs refs = createRefs();
        try {
            strategy.merge(createMergeRequest(), refs);
        } finally {
            assertNull(agent.resolveBranch(repository, refs.getMerge())); //Should not have written the merge ref
            assertEquals("017caf31eca7c46eb3d1800fcac431cfa7147a01",      //Should not have updated the from ref
                    agent.resolveHead(repository).getLatestCommit());
            assertEquals("0a943a29376f2336b78312d99e65da17048951db",      //Should not have updated the to ref
                    agent.resolveHead(secondaryRepository).getLatestCommit());
        }
    }

    private PullRequestAutoMergeRequest createMergeRequest() {
        return new PullRequestAutoMergeRequest.Builder(pullRequest)
                .author(author)
                .repositoryDir(config.getRepositoryDir(repository))
                .build();
    }

    private DefaultPullRequestRefs createRefs() {
        return new DefaultPullRequestRefs(agent, pullRequest);
    }
}
