package it.com.atlassian.stash.pull;

import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.webdriver.bitbucket.page.PullRequestCreatePage;
import com.atlassian.webdriver.bitbucket.page.PullRequestOverviewPage;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class PullRequestForkCreateTest extends BasePullRequestFuncTest {

    private static final String FORK_SLUG = REPO_SLUG + "-fork";
    private static final String FORK_USERNAME = "createtest";
    private static final String SOURCE_BRANCH_ID = "refs/heads/" + BRANCH_THAT_HAS_SAME_FILE_MODIFIED_AND_MOVED_SRC;
    private static final String TARGET_BRANCH_ID = "refs/heads/" + BRANCH_THAT_HAS_SAME_FILE_MODIFIED_AND_MOVED_TRGT;

    @BeforeClass
    public static void setup() {
        getClassTestContext().forkNonPersonal(PROJECT_KEY, REPO_SLUG, PROJECT_KEY, FORK_SLUG);

        getClassTestContext().user(FORK_USERNAME, FORK_USERNAME)
                .projectPermission(PROJECT_KEY, FORK_USERNAME, Permission.PROJECT_ADMIN)
                .fork(PROJECT_KEY, REPO_SLUG, FORK_USERNAME, FORK_USERNAME);
    }

    @Test
    public void testCreateFromForkToFork() {
        PullRequestCreatePage createPage = loginAsAdmin(PullRequestCreatePage.class, PROJECT_KEY, FORK_SLUG);

        testPRCreate(createPage, null, PROJECT_KEY, FORK_SLUG, false, PROJECT_NAME + " / " + FORK_SLUG);
    }

    @Test
    public void testCreateFromForkToPersonalFork() {
        PullRequestCreatePage createPage = loginAsAdmin(PullRequestCreatePage.class, PROJECT_KEY, FORK_SLUG);

        testPRCreate(createPage, FORK_USERNAME + "/" + REPO_SLUG, FORK_USERNAME, REPO_SLUG, true,
                PROJECT_NAME + " / " + FORK_SLUG);
    }

    @Test
    public void testCreateFromForkToSource() {
        PullRequestCreatePage createPage = loginAsAdmin(PullRequestCreatePage.class, PROJECT_KEY, FORK_SLUG);

        testPRCreate(createPage, PROJECT_NAME + "/" + REPO_SLUG, PROJECT_KEY, REPO_SLUG, false,
                PROJECT_NAME + " / " + FORK_SLUG);
    }

    @Test
    public void testCreateFromPersonalForkToFork() {
        PullRequestCreatePage createPage = loginAs(FORK_USERNAME, FORK_USERNAME, PullRequestCreatePage.class,
                "~" + FORK_USERNAME, REPO_SLUG);

        testPRCreate(createPage, PROJECT_NAME + "/" + FORK_SLUG, PROJECT_KEY, FORK_SLUG, false,
                FORK_USERNAME + " / " + REPO_SLUG);
    }

    @Test
    public void testCreateFromPersonalForkToPersonalFork() {
        PullRequestCreatePage createPage = loginAs(FORK_USERNAME, FORK_USERNAME, PullRequestCreatePage.class,
                "~" + FORK_USERNAME, REPO_SLUG);

        testPRCreate(createPage, FORK_USERNAME + "/" + REPO_SLUG, FORK_USERNAME, REPO_SLUG, true,
                FORK_USERNAME + " / " + REPO_NAME);
    }

    @Test
    public void testCreateFromPersonalForkToSource() {
        PullRequestCreatePage createPage = loginAs(FORK_USERNAME, FORK_USERNAME, PullRequestCreatePage.class,
                "~" + FORK_USERNAME, REPO_SLUG);

        testPRCreate(createPage, null, PROJECT_KEY, REPO_SLUG, false, FORK_USERNAME + " / " + REPO_SLUG);
    }

    @Test
    public void testCreateFromSourceToFork() {
        PullRequestCreatePage createPage = loginAsAdmin(PullRequestCreatePage.class, PROJECT_KEY, REPO_SLUG);

        testPRCreate(createPage, PROJECT_NAME + "/" + FORK_SLUG, PROJECT_KEY, FORK_SLUG, false,
                PROJECT_NAME + " / " + REPO_SLUG);
    }

    @Test
    public void testCreateFromSourceToPersonalFork() {
        PullRequestCreatePage createPage = loginAs(FORK_USERNAME, FORK_USERNAME, PullRequestCreatePage.class,
                PROJECT_KEY, REPO_SLUG);

        testPRCreate(createPage, FORK_USERNAME + "/" + REPO_SLUG, FORK_USERNAME, REPO_SLUG, true,
                PROJECT_NAME + " / " + REPO_SLUG);
    }

    private void testPRCreate(PullRequestCreatePage createPage, String targetRepo, String submissionProject,
                              String submissionRepo, boolean isPersonalFork, String fullSourceNamePrefix) {
        createPage.getSourceBranchSelector().open().selectItemById(SOURCE_BRANCH_ID);
        if (targetRepo != null) {
            createPage.getTargetRepositorySelector().open().selectItemByExactName(targetRepo);
        }
        createPage.getTargetBranchSelector().open().selectItemById(TARGET_BRANCH_ID);

        PullRequestOverviewPage activityPage;
        if (isPersonalFork) {
            activityPage = createPage.clickContinue().clickSubmitToPersonalFork(submissionProject, submissionRepo);
        } else {
            activityPage = createPage.clickContinue().clickSubmitToFork(submissionProject, submissionRepo);
        }

        try {
            assertEquals(fullSourceNamePrefix + " / " + BRANCH_THAT_HAS_SAME_FILE_MODIFIED_AND_MOVED_SRC,
                    activityPage.getFullSourceName());
        } finally {
            activityPage.getDeclineButton().clickButton().decline();
        }
    }
}
