package com.hdkj.lt.core.plugins.test;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.hdkj.lt.base.exception.ExceptionCast;
import com.hdkj.hussar.ApiResponse;
import com.hdkj.hussar.ResultCode;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.*;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author wucx
 * @Date 2022/11/9 16:36
 * @Version 1.0
 */
@Slf4j
@SpringBootTest
@WebAppConfiguration
@RunWith(SpringRunner.class)
public class BaseTest extends AbstractJUnit4SpringContextTests {

    //使用MockMvc进行测试
    protected MockMvc mockMvc;

    //创建context
    @Autowired
    private WebApplicationContext webApplicationContext;

    @Autowired
    private RestTemplate connPoolRestTemplate;

    private String tokenVerify;

    @Value("${lt.junit.url}")
    private String url;
    @Value("${lt.junit.userName}")
    private String userName;
    @Value("${lt.junit.password}")
    private String password;
    @Value("${hussar.core.encrypt.enable-pw-encryption}")
    private Boolean enablePwEncryption;

    @After()
    public void tearDown() {
        log.info("end.....");
    }

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
        tokenVerify = getHussarTokenValue();
    }

    /**
     * @param url    controller对应的地址 ： /api/pms/preplan
     * @param params 请求参数
     * @throws Exception
     */
    @SneakyThrows
    protected final void processGet(String url, MultiValueMap<String, String> params) {
        if (ObjectUtil.isNotNull(mockMvc)) {
            MockHttpServletRequestBuilder httpServletRequest = MockMvcRequestBuilders.get(url)
                    .header(SecurityOAuth2Constants.Param.swagger, SecurityOAuth2Constants.Param.swagger) //越过直接访问子服务校验
                    .header(SecurityOAuth2Manager.getConfig().getHeaderTokenKey(), tokenVerify) //设置token值
                    .params(params)
                    .contentType(MediaType.ALL_VALUE)
                    .accept(MediaType.ALL);
            MvcResult mvcResult = mockMvc.perform(httpServletRequest)
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    .andDo(MockMvcResultHandlers.print())
                    .andReturn();
            JSONObject result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString());
            Assert.assertEquals(ResultCode.SUCCESS.getCode(), Integer.parseInt(result.getString("code")), 1);
        }
    }

    /**
     * @param url    controller对应的地址 ： /api/pms/preplan
     * @param params 请求参数
     * @throws Exception
     */
    @SneakyThrows
    protected final void processPost(String url, MultiValueMap<String, String> params) {
        if (ObjectUtil.isNotNull(mockMvc)) {
            MockHttpServletRequestBuilder httpServletRequest = MockMvcRequestBuilders.post(url)
                    .header(SecurityOAuth2Constants.Param.swagger, SecurityOAuth2Constants.Param.swagger) //越过直接访问子服务校验
                    .header(SecurityOAuth2Manager.getConfig().getHeaderTokenKey(), tokenVerify) //设置token值
                    .params(params)
                    .contentType(MediaType.ALL_VALUE)
                    .accept(MediaType.ALL);
            MvcResult mvcResult = mockMvc.perform(httpServletRequest)
                    .andExpect(MockMvcResultMatchers.status().isOk())
                    .andDo(MockMvcResultHandlers.print())
                    .andReturn();
            JSONObject result = JSONObject.parseObject(mvcResult.getResponse().getContentAsString());
            Assert.assertEquals(ResultCode.SUCCESS.getCode(), Integer.parseInt(result.getString("code")), 1);
        }
    }

    @SneakyThrows
    protected final String getHussarTokenValue() {
        List<String> list = HussarCacheUtil.getKeysRightLike("hussar-token", "hussar-token:oauth2:access-token:");
        String token = list.stream().filter(e -> StringUtils.equals(e, list.get(list.size() - 1))).map(e -> e.substring(e.lastIndexOf(":") + 1)).collect(Collectors.joining());
        if (StringUtils.isEmpty(token)) {
            String pwEncryptKey = HussarCacheUtil.get("pw_encrypt_cache", "pw_encrypt_sm2_pub", String.class);
            if (StringUtils.isBlank(pwEncryptKey)) {
                ExceptionCast.cast("未获取到加密公钥信息！");
            }
            if (enablePwEncryption) { //默认不开启加密，直接赋值用户密码，开启加密时，获取密码的加密内容
                password = SM2Util.encrypt(password, pwEncryptKey);
            }
            // 获取HussarToken数据
            String authUri = String.format("%s/auth/oauth2/token?grant_type=password&username=%s&password=%s", url, userName, password);
            // 接口header信息
            HttpHeaders headers = new HttpHeaders();
            headers.set(SecurityOAuth2Constants.Param.client_id, "hussar-base");
            headers.setAccept(Lists.newArrayList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
            HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(headers);
            ResponseEntity<ApiResponse> respEntity = connPoolRestTemplate.exchange(authUri, HttpMethod.GET, formEntity, ApiResponse.class);
            if (ResultCode.SUCCESS.getCode() != Objects.requireNonNull(respEntity.getBody()).getCode()) {
                ExceptionCast.cast("HussarToken接口数据获取失败！");
            }
            JSONObject result = JSONObject.parseObject(JSON.toJSONString(Objects.requireNonNull(respEntity.getBody()).getData()));
            if (StringUtils.isBlank(Objects.requireNonNull(result).getString(SecurityOAuth2Constants.Param.access_token))) {
                ExceptionCast.cast("未获取到指定HussarToken信息！");
            }
            token = result.getString(SecurityOAuth2Constants.Param.access_token);
        }
        return token;
    }

}
