package com.usoftchina.bi.starter.test;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.JavaType;
import com.usoftchina.bi.core.base.RepEntity;
import org.junit.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * @Author chenwei
 * @Date 2019/03/01
 */
public class BaseControllerTest {

    @Autowired
    protected WebApplicationContext context;

    protected MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
                .alwaysDo(print())
                .alwaysExpect(isOk())
                .alwaysExpect(isJson())
                .build();
    }

    /**
     * GET请求
     *
     * @param urlTemplate
     * @return
     */
    public static MockHttpServletRequestBuilder get(String urlTemplate, Object... uriVars) {
        return MockMvcRequestBuilders.get(urlTemplate, uriVars);
    }

    /**
     * POST form方式请求
     *
     * @param urlTemplate
     * @return
     */
    public static MockHttpServletRequestBuilder post(String urlTemplate, Object... uriVars) {
        return MockMvcRequestBuilders.post(urlTemplate, uriVars);
    }

    /**
     * 文件上传
     *
     * @param urlTemplate
     * @param uriVars
     * @return
     */
    public static MockMultipartHttpServletRequestBuilder multipart(String urlTemplate, Object... uriVars) {
        return MockMvcRequestBuilders.multipart(urlTemplate, uriVars);
    }

    /**
     * 请求
     *
     * @param urlTemplate
     * @return
     */
    public static MockHttpServletRequestBuilder request(HttpMethod method, String urlTemplate, Object... uriVars) {
        return MockMvcRequestBuilders.request(method, urlTemplate, uriVars);
    }

    /**
     * POST Payload方式请求，使用@RequestBody注解情况下
     *
     * @param object
     * @return
     */
    public static MockHttpServletRequestBuilder requestBody(String urlTemplate, Object object) {
        return post(urlTemplate).contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(JSON.toJSONString(object));
    }

    /**
     * 是否返回 http status: 200
     *
     * @return
     */
    public static ResultMatcher isOk() {
        return status().isOk();
    }

    /**
     * 是否返回json格式
     *
     * @return
     */
    public static ResultMatcher isJson() {
        return content().contentType(MediaType.APPLICATION_JSON_UTF8);
    }

    /**
     * 是否执行成功 {"success": true}
     *
     * @return
     */
    public static ResultMatcher isSuccess() {
        return jsonPath("success").value(true);
    }

    /**
     * 是否执行失败 {"success": false}
     *
     * @return
     */
    public static ResultMatcher isFail() {
        return jsonPath("success").value(false);
    }

    /**
     * Result转换
     *
     * @param mvcResult
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> RepEntity<T> result(MvcResult mvcResult, Class<T> targetClass) throws Exception {
        String content = mvcResult.getResponse().getContentAsString();
        return RepEntity.fromJsonString(content, targetClass);
    }

    /**
     * Result转换
     *
     * @param mvcResult
     * @param targetType
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> RepEntity<T> result(MvcResult mvcResult, JavaType targetType) throws Exception {
        String content = mvcResult.getResponse().getContentAsString();
        return RepEntity.fromJsonString(content, targetType);
    }

}
