package it.com.atlassian.bitbucket.integrity;

import com.atlassian.bitbucket.test.DefaultFuncTestData;
import com.atlassian.bitbucket.test.ProjectTestHelper;
import com.atlassian.bitbucket.test.PullRequestTestHelper;
import com.atlassian.bitbucket.test.RepositoryTestHelper;
import com.jayway.restassured.RestAssured;
import com.jayway.restassured.response.Response;
import org.apache.commons.lang3.mutable.MutableLong;
import org.junit.rules.TemporaryFolder;
import org.springframework.core.io.ClassPathResource;

import static com.jayway.restassured.http.ContentType.JSON;
import static org.apache.http.HttpStatus.SC_CONFLICT;
import static org.apache.http.HttpStatus.SC_CREATED;
import static org.junit.Assert.fail;

public class SetupUtil {

    public static void createProject(String slug) {
        Response response = ProjectTestHelper.createProject(slug, slug + " Name", slug + " Description");
        if (response.statusCode() != SC_CREATED && response.statusCode() != SC_CONFLICT) {
            fail("Attempting to create the test project failed with status code " + response.statusCode());
        }
    }

    public static void createRepo(String project, String repo) {
        createRepo(project, repo, "git-repositories/" + project + "/" + repo + ".zip");
    }

    public static void createRepo(String project, String repo, String repoContent) {
        Response response = RepositoryTestHelper.createRepository(project, repo);
        if (response.statusCode() != SC_CREATED && response.statusCode() != SC_CONFLICT) {
            fail("Attempting to create the test repository failed with status code " + response.statusCode());
        }

        ClassPathResource repositoryResource = new ClassPathResource(repoContent);

        try {
            TemporaryFolder temporaryFolder = new TemporaryFolder();
            temporaryFolder.create();
            RepositoryTestHelper.pushRep(temporaryFolder, DefaultFuncTestData.getBaseURL(),
                    DefaultFuncTestData.getAdminUser(), DefaultFuncTestData.getAdminPassword(),
                    project, repo, repositoryResource);
        } catch (Exception e) {
            fail("Failed to push repository: " + e.getMessage());
        }
    }

    /**
     * @return the ID of the created pull request
     */
    public static long createPullRequest(String username, String password,
                                  String title, String description, String sourceProject,
                                  String sourceRepo, String sourceBranch, String targetProject,
                                  String targetRepo, String targetBranch) {
        MutableLong id = new MutableLong();
        PullRequestTestHelper.createPullRequest(id, username, password, title, description, sourceProject, sourceRepo,
                sourceBranch, targetProject, targetRepo, targetBranch);
        return id.getValue();
    }

    /**
     * Can be used to store a value in plugin settings.
     * Useful for passing data between setup and assert stages.
     *
     * Uses user settings under the hood to store the data in the instance.
     * @param key the value key
     * @param value the value
     */
    public static void storeValue(String key, long value) {
        RestAssured.expect()
                .statusCode(204)
                .given()
                .contentType(JSON)
                .auth().preemptive().basic(DefaultFuncTestData.getAdminUser(), DefaultFuncTestData.getAdminPassword())
                .body("{\"" + key + "\": " + value + "}")
                .when()
                .post(DefaultFuncTestData.getRestURL()
                        .concat("/users/" + DefaultFuncTestData.getAdminUser() + "/settings"));
    }
}
