package com.live.client;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.live.utils.*;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.util.StringUtils;
import org.testng.Assert;
import org.testng.ITestResult;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;

import java.util.*;

@ContextConfiguration(locations = {"classpath:/spring-core.xml"})
public class ApiTest extends AbstractTestNGSpringContextTests {

    public static RestfulClient httpclient = null;
    public static SSLRestfulClient sslhttpclient = null;
    public static OkHttpClient okHttpClient = null;
    // 支持业务数据方法参数

    private static String host = null;
    private static String url = null;
    private Properties prop = null;
    public static UtDal dal = new UtDal();
    private static CommonRequestParameters loginInfo;
    private ApiResult apiResult = new ApiResult();


    public ApiTest() { }

    @BeforeClass
    public static void beforeClass() {
        httpclient = new RestfulClient();
        sslhttpclient = new SSLRestfulClient();
        okHttpClient = new OkHttpClient();

    }

    /**
     * 测试接口调用API
     */
    @BeforeMethod
    public void beforeTest() {
    }
    /**
     * 测试接口调用API
     */

    public void initApi(XMAppApi xmAppApi) {
        clearApiData(xmAppApi);// 清空上次API调用信息
        dataPreparation(xmAppApi);
    }

    private void  clearApiData(XMAppApi api){
        api.setApi_request_params(new IdentityHashMap());
        api.setApi_request_data(null);
        api.setApi_request_headers(new HashMap<>());
        api.setApi_response(null);
        api.setApi_traceId(null);
    }
    /**
     * 数据业务方法调用  可选参数userInfos  测试时需要切换端位时传入要登录的user信息
     */
    public  void beforeDataRequest(XMAppApi dataApi, DataUserInfo...userInfos){

        clearApiData(dataApi);// 清空上次API调用信息
        // 默认同端位接口调用， dataApi 使用被测试接口信息里的 登录信息
      /*  dataApi.setLoginUser(xmAppApi.getLoginUser())         // http 接口，测试账号
                .setTerminal(xmAppApi.getTerminal())
                .setEnv(xmAppApi.getEnv());            // 所属端位（B端，C端，M端等, 必传）*/
        // 支持切换端位调用
        if(userInfos.length>0){
            DataUserInfo info = userInfos[0];
            Assert.assertNotNull(info,"userInfos 为空！！！");
            if(!StringUtils.isEmpty(info.getLoginUser())){
                dataApi.setLoginUser(info.getLoginUser());
            }
            if(!StringUtils.isEmpty(info.getTerminal())){
                dataApi.setTerminal(info.getTerminal());
            }
        }
        dataPreparation(dataApi);
    }



    /**
     *   业务API调用专用
     */
    private void dataPreparation(XMAppApi executionApi) {
        Assert.assertNotNull(executionApi.getApiModule(), "必要的api信息不存在！");
        prop = CommUtil.getconfig();
        JsonAndFile fileHandle = new JsonAndFile();

        String apiModule = prop.getProperty(executionApi.getApiModule());
        // 获取接口模块参数
        String fileParam = fileHandle.readTxtFile(System.getProperty("user.dir") + apiModule);
        Assert.assertNotNull(fileParam, "必要的API模块信息未找到，请检查api模块文件路径！");

        JSONObject api = (JSONObject) JSON.parseObject(fileParam).get(executionApi.getApiName());
        Assert.assertNotNull(api, "必要的API接口信息未找到，请检查apiName信息！");
        executionApi.setApiDesc(api.getString("apiName"));
        /**
         * 测试环境测试
         * M端测试默认使用rc 环境
         * 其他系统测试默认使用线上
         */
        String env = "rc";
        if (!StringUtils.isEmpty(executionApi.getEnv())) {
            env = executionApi.getEnv();
        } /*else if (executionApi.getTerminal().equals("M")) {
            env = "rc";
        } */
        host = prop.getProperty(env);

//            预置登陆信息
        CommonLoginInfo loginInfoMap = (CommonLoginInfo) SpringContextUtil.getBean("commonLoginInfoMap");
        loginInfo = loginInfoMap.get(executionApi.getLoginUser());
        if (StringUtils.isEmpty(loginInfo.getToken())) {
            CommonLogin common_login = new CommonLogin();
            common_login.login(env, executionApi.getLoginUser(), executionApi.getTerminal());
            loginInfo = loginInfoMap.get(executionApi.getLoginUser());
        }

        // 组装URL
        url = host + api.getString("apiPath") + loginInfo.getCommonParam(executionApi.getTerminal());
        executionApi.setUrl(url);
//          请求头设置
        if ("B".equals(executionApi.getTerminal())) {
            executionApi.getHeadrs().put("instid", loginInfo.getInstId());
            executionApi.getHeadrs().put("bizAccountId", loginInfo.getAid());
            executionApi.getHeadrs().put("xmversion", "5.0");
            executionApi.getHeadrs().put("vn", "5.4.0");
        } else if ("M".equals(executionApi.getTerminal())) {
            executionApi.getHeadrs().put("usertype", loginInfo.getUserType());
            executionApi.getHeadrs().put("deptpath", loginInfo.getDeptpath());
        }

        executionApi.getHeadrs().put("xm_request_source", "test");
        executionApi.getHeadrs().put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36");
        executionApi.getHeadrs().put("Accept", "*/*");
        executionApi.getHeadrs().put("Connection", "Keep-Alive");
        // 接口未设置请求头，则默认为 application/json
        if (api.containsKey("apiContentType") || StringUtils.isEmpty(api.getString("apiContentType"))) {
            executionApi.getHeadrs().put("Content-type", "application/json;charset=utf-8");
        } else {
            executionApi.getHeadrs().put("Content-type", api.getString("apiContentType"));
        }
    }

    /**
     * @param xmAppApi
     * @param requestType 请求类型
     */
    public XMAppApi doRequest(XMAppApi xmAppApi, String requestType) {
        OkHttpClient okHttpClient = new OkHttpClient();
        switch (requestType) {
            case "JSON":
                okHttpClient.doPostRequest(xmAppApi.getUrl(),  xmAppApi.getDataJson(), xmAppApi.getHeadrs());
                break;
            case "PARAM":
                okHttpClient.doPostRequest(xmAppApi.getUrl(), xmAppApi.getParams(), xmAppApi.getHeadrs());
                break;
            case "FORM":
                okHttpClient.doPostForForm(xmAppApi.getUrl(), xmAppApi.getParams(), xmAppApi.getHeadrs());
                break;
            case "GET":
                okHttpClient.doGetRequest(xmAppApi.getUrl(), xmAppApi.getParams(),  xmAppApi.getHeadrs());
                break;
        }

        Map<String, String> head = okHttpClient.getHeaders();
        String response = okHttpClient.getBody();
        xmAppApi.setApi_response(response) ;
        xmAppApi.setApi_traceId(head.get("traceId")) ;
        xmAppApi.setApi_request_data(xmAppApi.getDataJson());
        xmAppApi.setApi_request_params(xmAppApi.getParams());
        xmAppApi.setApi_request_headers(head) ;

        apiResult.setApi_response(response) ;
        apiResult.setApi_traceId(head.get("traceId")) ;
        apiResult.setApi_request_data(xmAppApi.getDataJson());
        apiResult.setApi_request_params(xmAppApi.getParams());
        apiResult.setApi_request_headers(head) ;
        return  xmAppApi;
    }

    @AfterMethod
    public void afterMethod(ITestResult result) {
        List<NameValuePair> params=new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("Host",apiResult.getUrl()));
        params.add(new BasicNameValuePair("traceId",apiResult.getApi_traceId()));
        params.add(new BasicNameValuePair("RequestParams",apiResult.getApi_request_params().toString()));
        params.add(new BasicNameValuePair("RequestData",apiResult.getApi_request_data()));
        params.add(new BasicNameValuePair("Response",apiResult.getApi_response()));
        result.setParameters(params.toArray());
        result.setAttribute("ApiDesc",apiResult.getApiDesc());
    }

    @AfterClass
    public static void afterClass() {
        httpclient.shutDownConnection();
        sslhttpclient.shutDownConnection();
    }
}
