package it.com.atlassian.stash.rest.task;

import com.atlassian.bitbucket.test.PullRequestTestHelper;
import com.atlassian.bitbucket.test.TaskTestHelper;
import com.jayway.restassured.RestAssured;
import org.junit.BeforeClass;
import org.junit.Test;

import static javax.ws.rs.core.Response.Status.*;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.startsWith;

public class TaskDeleteResourceTest extends AbstractTaskResourceTest {

    private static PullRequestTestHelper pullRequest;

    @BeforeClass
    public static void setupRepository() throws Exception {
        defaultSetupRepository(getClassTestContext());
        pullRequest = getClassTestContext().pullRequest(
                new PullRequestTestHelper.Builder(
                        USER_PR_AUTHOR, USER_PR_AUTHOR,
                        PR_TITLE, PR_TITLE,
                        PROJECT_NAME, PROJECT_NAME, SOURCE_BRANCH,
                        PROJECT_NAME, PROJECT_NAME, TARGET_BRANCH));
    }

    @Test
    public void testTaskCreatorCanDeleteTask() throws Exception {
        TaskTestHelper task = createTask(testContext, pullRequest);

        RestAssured
            .given().auth().preemptive().basic(USER_TASK_CREATOR, USER_TASK_CREATOR)
            .when().delete(task.getResourceUrl())
            .then().statusCode(NO_CONTENT.getStatusCode());

        RestAssured
            .given().auth().preemptive().basic(USER_TASK_CREATOR, USER_TASK_CREATOR)
            .when().get(task.getResourceUrl())
            .then().statusCode(NOT_FOUND.getStatusCode());
    }

    @Test
    public void testPullRequestAuthorCanDeleteTask() throws Exception {
        TaskTestHelper task = createTask(testContext, pullRequest);

        RestAssured
            .given().auth().preemptive().basic(USER_PR_AUTHOR, USER_PR_AUTHOR)
            .when().delete(task.getResourceUrl())
            .then().statusCode(NO_CONTENT.getStatusCode());

        RestAssured
            .given().auth().preemptive().basic(USER_TASK_CREATOR, USER_TASK_CREATOR)
            .when().get(task.getResourceUrl())
            .then().statusCode(NOT_FOUND.getStatusCode());
    }

    @Test
    public void testAdminCanDeleteTask() throws Exception {
        TaskTestHelper task = createTask(testContext, pullRequest);

        RestAssured
            .given().auth().preemptive().basic(USER_REPO_ADMIN, USER_REPO_ADMIN)
            .when().delete(task.getResourceUrl())
            .then().statusCode(NO_CONTENT.getStatusCode());

        RestAssured
            .given().auth().preemptive().basic(USER_TASK_CREATOR, USER_TASK_CREATOR)
            .when().get(task.getResourceUrl())
            .then().statusCode(NOT_FOUND.getStatusCode());
    }

    @Test
    public void testCannotDeleteResolvedTask() throws Exception {
        TaskTestHelper task = createTask(testContext, pullRequest);
        task.resolve();

        RestAssured
                .given().auth().preemptive().basic(USER_REPO_ADMIN, USER_REPO_ADMIN)
                .when().delete(task.getResourceUrl())
                .then()
                    .log().ifValidationFails()
                    .statusCode(CONFLICT.getStatusCode())
                    .body(FIRST_ERROR_MESSAGE, equalTo("You cannot delete a resolved task."));

    }

    @Test
    public void testCannotDeleteDeletedTask() throws Exception {
        TaskTestHelper task = createTask(testContext, pullRequest);

        task.delete();

        RestAssured
            .given().auth().preemptive().basic(USER_REPO_ADMIN, USER_REPO_ADMIN)
            .when().delete(task.getResourceUrl())
            .then().statusCode(NOT_FOUND.getStatusCode());
    }

    @Test
    public void testCannotDeleteNonExistentTask() throws Exception {
        RestAssured
                .given().auth().preemptive().basic(USER_REPO_ADMIN, USER_REPO_ADMIN)
                .when().delete(TaskTestHelper.getResourceUrl(Long.MAX_VALUE))
                .then().statusCode(NOT_FOUND.getStatusCode());
    }

    @Test
    public void testAnonymousUserCannotDeleteTask() throws Exception {
        TaskTestHelper task = createTask(testContext, pullRequest);

        RestAssured
            .when().delete(task.getResourceUrl())
            .then()
                .log().ifValidationFails()
                .statusCode(UNAUTHORIZED.getStatusCode())
                .body("message", equalTo("You are not permitted to access this resource"));

        RestAssured
                .given().auth().preemptive().basic(USER_TASK_CREATOR, USER_TASK_CREATOR)
                .when().get(task.getResourceUrl())
                .then().statusCode(OK.getStatusCode());
    }

    @Test
    public void testPullRequestParticipantCannotDeleteTask() throws Exception {
        TaskTestHelper task = createTask(testContext, pullRequest);

        RestAssured
            .given().auth().preemptive().basic(USER_PARTICIPANT, USER_PARTICIPANT)
            .when().delete(task.getResourceUrl())
            .then()
                .log().ifValidationFails()
                .statusCode(UNAUTHORIZED.getStatusCode())
                .body(FIRST_ERROR_MESSAGE, equalTo("You do not have permission to delete this task."));

        RestAssured
            .given().auth().preemptive().basic(USER_TASK_CREATOR, USER_TASK_CREATOR)
            .when().get(task.getResourceUrl())
            .then().statusCode(OK.getStatusCode());
    }

    @Test
    public void testDeleteTaskByPullRequestParticipantShouldThrowUnAuthorizedExceptionEvenIfTaskIsResolved() throws Exception {
        TaskTestHelper task = createTask(testContext, pullRequest);
        task.resolve();

        RestAssured
                .given().auth().preemptive().basic(USER_PARTICIPANT, USER_PARTICIPANT)
                .when().delete(task.getResourceUrl())
                .then()
                    .log().ifValidationFails()
                    .statusCode(UNAUTHORIZED.getStatusCode())
                    .body(FIRST_ERROR_MESSAGE, equalTo("You do not have permission to delete this task."));

        RestAssured
                .given().auth().preemptive().basic(USER_TASK_CREATOR, USER_TASK_CREATOR)
                .when().get(task.getResourceUrl())
                .then().statusCode(OK.getStatusCode());
    }

    @Test
    public void testDeleteTaskShouldThrowNotFoundForNonPermittedUser() throws Exception {
        TaskTestHelper task = createTask(testContext, pullRequest);

        RestAssured
            .given().auth().preemptive().basic(USER_CANNOT_READ, USER_CANNOT_READ)
            .when().delete(task.getResourceUrl())
            .then()
                .log().ifValidationFails()
                .statusCode(NOT_FOUND.getStatusCode())
                .body(FIRST_ERROR_MESSAGE, startsWith("There is no task with ID"));

        RestAssured
            .given().auth().preemptive().basic(USER_TASK_CREATOR, USER_TASK_CREATOR)
            .when().get(task.getResourceUrl())
            .then().statusCode(OK.getStatusCode());
    }
}
