package it.com.atlassian.stash.pull;

import com.atlassian.bitbucket.test.BranchModelTestHelper;
import com.atlassian.webdriver.bitbucket.page.InlineMergeWarningDialog;
import com.atlassian.webdriver.bitbucket.page.MergeHelpDialog;
import com.atlassian.webdriver.bitbucket.page.PullRequestOverviewPage;
import com.atlassian.webdriver.bitbucket.page.PullRequestRepositorySettingsPage;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.Optional;

import static com.atlassian.bitbucket.test.BranchModelTestHelper.*;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

public class PullRequestMergeHelpTest extends BasePullRequestFuncTest {

    @Before
    public void setupPullRequest() {
        loginAsAdmin(PullRequestRepositorySettingsPage.class, PROJECT_KEY, REPO_SLUG)
                .setNumberOfRequiredApprovers(1)
                .clickSave();
    }

    @Test
    public void testAutoMergeConflictInstructions() {
        BranchModelTestHelper branchModelTestHelper = new BranchModelTestHelper(PROJECT_KEY, REPO_SLUG);
        branchModelTestHelper.enable(createBranchModelJson(
                createBranchConfiguration("refs/heads/master", false), null,
                createBranchTypeConfiguration("RELEASE", "automerge_conflict/", true)
        ));
        branchModelTestHelper.enableAutoMerge();

        long pullRequestId = createPullRequest(new PullRequestBuilder(BRANCH_WITH_AUTOMERGE_CONFLICT_SRC,
                BRANCH_WITH_AUTOMERGE_CONFLICT_TRGT).build()).getId();
        try {
            testConflictInstructions(pullRequestId, BRANCH_WITH_AUTOMERGE_CONFLICT_SRC,
                    BRANCH_WITH_AUTOMERGE_CONFLICT_TRGT);
        } finally {
            declinePullRequest(pullRequestId);
        }
    }

    @Test
    public void testMergeWithoutApprovalDisabled() {
        long pullRequestId = createPullRequest(new PullRequestBuilder(BRANCH_THAT_HAS_SAME_FILE_MODIFIED_AND_MOVED_SRC,
                BRANCH_THAT_HAS_SAME_FILE_MODIFIED_AND_MOVED_TRGT).build()).getId();
        try {
            PullRequestOverviewPage overviewPage = loginAsAdmin(PullRequestOverviewPage.class, PROJECT_KEY, REPO_SLUG,
                    pullRequestId);

            assertFalse("Merge button should be disabled", overviewPage.getMergeButton().isEnabled());

            Optional<InlineMergeWarningDialog> dialog = overviewPage.openMergeInlineWarnings();
            assertTrue("There should be a merge warning dialog box", dialog.isPresent());
            List<String> warnings = dialog.get().getWarnings();
            assertThat(warnings, hasSize(1));
            assertThat(warnings.get(0), equalTo("You need 1 more approval before this pull request can be merged."));
        } finally {
            declinePullRequest(pullRequestId);
        }
    }

    @Test
    public void testMergeConflictInstructions() {
        long pullRequestId = createPullRequest(new PullRequestBuilder(BRANCH_THAT_HAS_SAME_TEXT_FILE_MODIFIED_SRC,
                BRANCH_THAT_HAS_SAME_TEXT_FILE_MODIFIED_TRGT).build()).getId();
        try {
            testConflictInstructions(pullRequestId, BRANCH_THAT_HAS_SAME_TEXT_FILE_MODIFIED_SRC,
                    BRANCH_THAT_HAS_SAME_TEXT_FILE_MODIFIED_TRGT);
        } finally {
            declinePullRequest(pullRequestId);
        }
    }

    private void checkMergeInstructions(MergeHelpDialog mergeHelpDialog, String fetchBranch, String checkoutBranch) {
        List<String> instructions = mergeHelpDialog.getInstructions();
        instructions.contains(String.format("git fetch origin %s", fetchBranch));
        instructions.contains(String.format("git checkout %s \ngit merge FETCH_HEAD", checkoutBranch));
    }

    private void testConflictInstructions(long pullRequestId, String sourceBranch, String targetBranch) {
        PullRequestOverviewPage overviewPage =
                loginAsAdmin(PullRequestOverviewPage.class, PROJECT_KEY, REPO_SLUG, pullRequestId);

        assertFalse("Merge button should be disabled", overviewPage.getMergeButton().isEnabled());

        checkMergeInstructions(overviewPage.openMergeHelpDialog(), sourceBranch, targetBranch);
    }
}
