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

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

import static com.atlassian.bitbucket.hamcrest.MoreMatchers.longEqual;
import static javax.ws.rs.core.Response.Status.OK;
import static org.hamcrest.Matchers.*;

public class CommentTaskResourceTest 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 testWhenNoTasksAreAttachedToAComment() throws Exception {
        PullRequestComment comment = createComment(pullRequest);

        RestAssured
            .given()
                .auth().preemptive().basic(USER_PR_AUTHOR, USER_PR_AUTHOR)
            .when()
                .get(comment.getGetUrl())
            .then()
                .statusCode(OK.getStatusCode())
                .body("tasks", notNullValue())
                .body("tasks", iterableWithSize(0));
    }

    @Test
    public void testReturnedTasksOrderedByStateThenCreateDate() throws Exception {
        PullRequestComment comment = createComment(pullRequest);

        TaskTestHelper[] t = {createTask(testContext, comment.pullRequestId, comment.commentId, "z"),
                              createTask(testContext, comment.pullRequestId, comment.commentId, "y"),
                              createTask(testContext, comment.pullRequestId, comment.commentId, "x"),
                              createTask(testContext, comment.pullRequestId, comment.commentId, "w"),
                              createTask(testContext, comment.pullRequestId, comment.commentId, "v")};

        t[3].resolve();
        t[1].resolve();

        RestAssured
            .given()
                .auth().preemptive().basic(USER_PR_AUTHOR, USER_PR_AUTHOR)
            .when()
                .get(comment.getGetUrl())
            .then()
                .log().ifValidationFails()
                .statusCode(OK.getStatusCode())
                .body("tasks", iterableWithSize(5))

                // check the order of the tasks
                .body("tasks[0]." + ID, longEqual(t[0].getId()))
                .body("tasks[0]." + STATE, equalTo(TaskState.OPEN.name()))
                .body("tasks[1]." + ID, longEqual(t[2].getId()))
                .body("tasks[1]." + STATE, equalTo(TaskState.OPEN.name()))
                .body("tasks[2]." + ID, longEqual(t[4].getId()))
                .body("tasks[2]." + STATE, equalTo(TaskState.OPEN.name()))
                .body("tasks[3]." + ID, longEqual(t[1].getId()))
                .body("tasks[3]." + STATE, equalTo(TaskState.RESOLVED.name()))
                .body("tasks[4]." + ID, longEqual(t[3].getId()))
                .body("tasks[4]." + STATE, equalTo(TaskState.RESOLVED.name()))

                // check the details of one opened task in detail
                .body("tasks[1]." + STATE, equalTo(TaskState.OPEN.name()))
                .body("tasks[1]." + TEXT, equalTo(t[2].getText()))
                .body("tasks[1]." + ANCHOR_ID, longEqual(t[2].getCommentId()))
                .body("tasks[1]." + CREATED_BY, equalTo(t[2].getAuthor()))
                .body("tasks[1]." + CREATED_DATE, hasToString(t[2].getCreatedDate()))
                .body("tasks[1]." + PERMITTED_OPERATIONS, notNullValue())
                .body("tasks[1]." + DELETABLE, equalTo(true))
                .body("tasks[1]." + EDITABLE, equalTo(true))
                .body("tasks[1]." + TRANSITIONABLE, equalTo(true))

                // check the permissions of one resolved task
                .body("tasks[4]." + STATE, equalTo(TaskState.RESOLVED.name()))
                .body("tasks[4]." + PERMITTED_OPERATIONS, notNullValue())
                .body("tasks[4]." + DELETABLE, equalTo(false))
                .body("tasks[4]." + EDITABLE, equalTo(false))
                .body("tasks[4]." + TRANSITIONABLE, equalTo(true));
    }

    @Test
    public void testWhenMultipleTasksOnComment() throws Exception {
        PullRequestComment comment = createComment(pullRequest);

        int taskCount = 5;
        for (int i = 0; i < taskCount; ++i) {
            createTask(testContext, comment.pullRequestId, comment.commentId, Integer.toString(i));
        }

        ValidatableResponse response = RestAssured
            .given()
                .auth().preemptive().basic(USER_PR_AUTHOR, USER_PR_AUTHOR)
            .when()
                .get(comment.getGetUrl())
            .then()
                .log().ifValidationFails()
                .statusCode(OK.getStatusCode())
                .body("tasks", iterableWithSize(taskCount));

        for (int i = 0; i < taskCount; i++) {
            response.body("tasks[" + i + "]." + TEXT, equalTo(Integer.toString(i)));
        }
    }

    @Test
    public void testCommentWithTasksIsDeletable() throws Exception {
        PullRequestComment comment = createComment(pullRequest);
        createTask(testContext, comment.pullRequestId, comment.commentId, "z");

        RestAssured
            .given()
                .auth().preemptive().basic(USER_PR_AUTHOR, USER_PR_AUTHOR)
            .when()
                .get(comment.getGetUrl())
            .then()
                .log().ifValidationFails()
                .statusCode(OK.getStatusCode())
                .body("permittedOperations.editable", equalTo(true))
                .body("permittedOperations.deletable", equalTo(true));
    }
}
