package com.atlassian.bitbucket.test.rest.comment;

import com.atlassian.bitbucket.content.DiffFileType;
import com.atlassian.bitbucket.content.DiffSegmentType;
import com.atlassian.bitbucket.test.DefaultFuncTestData;
import com.atlassian.bitbucket.test.RestTestHelper;
import com.jayway.restassured.builder.ResponseSpecBuilder;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.mutable.MutableLong;

import javax.ws.rs.core.Response;

import static java.util.Optional.ofNullable;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;

public class RestCommentUtils {

    public static JSONObject createAnchorBody(String path, String srcPath) {
        JSONObject anchor = new JSONObject();
        anchor.put("path", path);
        anchor.put("srcPath", srcPath);

        return anchor;
    }

    public static JSONObject createBody(String text) {
        JSONObject body = new JSONObject();
        body.put("text", text);

        return body;
    }

    public static JSONObject createBodyWithVersion(String text, int version) {
        JSONObject body = createBody(text);
        body.put("version", version);

        return body;
    }

    public static JSONObject createFileBody(String text, String path, String srcPath) {
        JSONObject body = createBody(text);
        body.put("anchor", createAnchorBody(path, srcPath));

        return body;
    }

    public static JSONObject createLineBody(String text, String path, String srcPath, int line,
                                            DiffSegmentType lineType) {
        return createLineBody(text, path, srcPath, line, lineType, (String) null);
    }

    public static JSONObject createLineBody(String text, String path, String srcPath, int line,
                                            DiffSegmentType lineType, String fileType) {
        return createLineBody(text, path, srcPath, line,
                ofNullable(lineType).map(DiffSegmentType::name).orElse(null), fileType);
    }

    public static JSONObject createLineBody(String text, String path, String srcPath, int line,
                                            DiffSegmentType lineType, DiffFileType fileType) {
        return createLineBody(text, path, srcPath, line,
                ofNullable(lineType).map(DiffSegmentType::name).orElse(null),
                ofNullable(fileType).map(DiffFileType::name).orElse(null));
    }

    public static JSONObject createLineBody(String text, String path, String srcPath, int line,
                                            String lineType, DiffFileType fileType) {
        return createLineBody(text, path, srcPath, line, lineType,
                ofNullable(fileType).map(DiffFileType::name).orElse(null));
    }

    public static JSONObject createLineBody(String text, String path, String srcPath, int line,
                                            String lineType, String fileType) {
        JSONObject anchor = createAnchorBody(path, srcPath);
        anchor.put("line", line);
        if (lineType != null) {
            anchor.put("lineType", lineType);
        }
        if (fileType != null) {
            anchor.put("fileType", fileType);
        }

        JSONObject body = createBody(text);
        body.put("anchor", anchor);

        return body;
    }

    public static JSONObject createReplyBody(String text, long parentId) {
        JSONObject parent = new JSONObject();
        parent.put("id", parentId);

        JSONObject body = createBody(text);
        body.put("parent", parent);

        return body;
    }

    public static ResponseSpecBuilder createSpecBuilder(Response.Status status, MutableLong commentId, String text,
                                                        String authorName) {
        return new ResponseSpecBuilder().expectStatusCode(status.getStatusCode())
                .expectBody("text", equalTo(text))
                .expectBody("id", RestTestHelper.captureLongId(commentId))
                .expectBody("version", equalTo(0))
                .expectBody("createdDate", notNullValue())
                .expectBody("updatedDate", notNullValue())
                .expectBody("author", notNullValue())
                .expectBody("author.name", equalTo(authorName))
                .expectBody("comments", notNullValue());
    }

    public static ResponseSpecBuilder createSpecBuilderWithNoReplies(Response.Status status, MutableLong commentId,
                                                                     String text, String authorName) {
        return createSpecBuilder(status, commentId, text, authorName)
                .expectBody("comments.size()", equalTo(0));
    }

    public static String getCommitDiscussionCommentsUrl(String projectKey, String repositorySlug, String commitId) {
        return DefaultFuncTestData.getRepositoryRestURL(projectKey, repositorySlug) +
                "/commits/" + commitId + "/comments";
    }

    public static String getPullRequestCommentsUrl(String projectKey, String repositorySlug, long pullRequestId) {
        return DefaultFuncTestData.getRepositoryRestURL(projectKey, repositorySlug) +
                "/pull-requests/" + pullRequestId + "/comments";
    }
}
