package com.live.client;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.live.utils.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.util.StringUtils;
import org.testng.*;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.internal.InvokedMethod;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

public class BaseTest extends AbstractTestNGSpringContextTests {

    private static final Log logger = LogFactory.getLog(BaseTest.class);

    public static RestfulClient httpclient = null;
    public static SSLRestfulClient sslhttpclient = null;
    public static OkHttpClient okHttpClient = null;
    public static HashMap<String, String> headers;
    public static IdentityHashMap<String, String> params;


    //    该map 主要用于rest-assured 风格请求参数组装预置对象
    public static Map restParams;
    public static Map miniAppRestParams;
    public static Map restParamsAnother;

    private static String host = null;
    public static String url = null;
    private Properties prop = null;
    public static UtDal dal;
    public static volatile XMAppApi xmAppApi;
    private static CommonRequestParameters loginInfo;

    // 支持业务数据方法参数
    public static HashMap<String, String> dataheadrs;
    public static IdentityHashMap<String, String> dataparams;

    public static XMAppApi dataApi;

    private static final Logger LOGGER = LoggerFactory.getLogger(com.live.client.BaseTest.class);

    public BaseTest() {
    }


    @BeforeClass
    public static void beforeClass() {
        httpclient = new RestfulClient();
        sslhttpclient = new SSLRestfulClient();
        okHttpClient = new OkHttpClient();
        xmAppApi = new XMAppApi();
        dal = new UtDal();
    }


    /**
     * 测试接口调用API
     */
    @BeforeMethod
    public void beforeTest() {
        // 每次执行测试case 前，初始化公共信息对象
        params = new IdentityHashMap<>();
        restParams = new HashMap();
        miniAppRestParams = new HashMap();
        restParamsAnother = new HashMap();
        dataparams = new IdentityHashMap<>();
        dataApi = new XMAppApi();

        clearApiData(xmAppApi);// 清空上次API调用信息
        headers = new HashMap<String, String>();
        dataPreparation(xmAppApi, headers);
    }


    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(DataUserInfo... userInfos) {

        clearApiData(dataApi);// 清空上次API调用信息

        dataheadrs = new HashMap<String, String>();
        // 默认同端位接口调用， dataApi 使用被测试接口信息里的 登录信息
        dataApi.setLoginUser(xmAppApi.getLoginUser())         // http 接口，测试账号
                .setTerminal(xmAppApi.getTerminal());
        // 支持切换端位调用
        if (userInfos.length > 0) {
            logger.info(userInfos[0]);
            if (!StringUtils.isEmpty(userInfos[0].getLoginUser())) {
                dataApi.setLoginUser(userInfos[0].getLoginUser());
            }
            if (!StringUtils.isEmpty(userInfos[0].getTerminal())) {
                dataApi.setTerminal(userInfos[0].getTerminal());
            }
        }
        dataPreparation(dataApi, dataheadrs);
    }

    /**
     * 业务API调用专用
     */

    private void dataPreparation(XMAppApi executionApi, HashMap<String, String> executionHeaders) {
//        Assert.assertNotNull(executionApi.getApiModule(), "必要的api信息不存在！");
        prop = CommUtil.getconfig();
        JsonAndFile fileHandle = new JsonAndFile();

        String apiModule = prop.getProperty(executionApi.getApiModule());
        logger.info(executionApi.getApiModule());
        // 获取接口模块参数
        String fileParam = fileHandle.readTxtFile(System.getProperty("user.dir") + apiModule);
//        Assert.assertNotNull(fileParam, "必要的API模块信息未找到，请检查api模块文件路径！");
        JSONObject api=null;
        if (fileParam.isEmpty()){
            logger.error("必要的API模块信息未找到，请检查api模块文件路径！");
        }else {
            api = (JSONObject) JSON.parseObject(fileParam).get(executionApi.getApiName());
            logger.info(api);
            executionApi.setApiDesc(api.getString("apiName"));
            if (api.containsKey("requestParamter")) {
                executionApi.setRequestParamterTemplate(api.getString("requestParamter"));
            }
        }

        /**
         * 默认执行线上环境
         */
        String env = "prod";
        if (xmAppApi.getTerminal().equals("M")){
            env="rc";
        }

        host = prop.getProperty(env);

        //            预置登陆信息
        CommonLoginInfo loginInfoMap = (CommonLoginInfo) SpringContextUtil.getBean("commonLoginInfoMap");
        loginInfo = loginInfoMap.get(executionApi.getLoginUser());

//        判断login， getToken信息是否为空
        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);
//        业务url
        logger.info("业务请求URL==>>"+url);

//          请求头设置
        if ("B".equals(executionApi.getTerminal())) {
            executionHeaders.put("instid", loginInfo.getInstId());
            executionHeaders.put("bizAccountId", loginInfo.getAid());
            executionHeaders.put("xmversion", "5.0");
            executionHeaders.put("vn", "5.4.0");
        } else if ("M".equals(executionApi.getTerminal())) {
            executionHeaders.put("usertype", loginInfo.getUserType());
            executionHeaders.put("deptpath", loginInfo.getDeptpath());
        }

        executionHeaders.put("xm_request_source", "test");
        executionHeaders.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");
        executionHeaders.put("Accept", "*/*");
        executionHeaders.put("Connection", "Keep-Alive");
        // 接口未设置请求头，则默认为 application/json
        if (api.containsKey("apiContentType") || StringUtils.isEmpty(api.getString("apiContentType"))) {
            executionHeaders.put("Content-type", "application/json;charset=utf-8");
        } else {
            executionHeaders.put("Content-type", api.getString("apiContentType"));
        }
    }

    private String getTestName(ITestResult test) {
        ITestNGMethod testMethod = test.getMethod();
        ITestContext context = test.getTestContext();
        TestRunner run = (TestRunner) context;
        String parameters = "";
        Class<?> clazz = run.getClass();
        try {
            Field field = clazz.getDeclaredField("m_invokedMethods");
            field.setAccessible(true);
            List<InvokedMethod> list = (List<InvokedMethod>) field.get(run);
            for (InvokedMethod in : list) {
                if (testMethod.getMethodName().equals(in.getTestMethod().getMethodName())) {
                    Class<?> clazz_in = in.getClass();
                    Field field_in = clazz_in.getDeclaredField("m_parameters");
                    field_in.setAccessible(true);
                    Object[] ab = (Object[]) field_in.get(in);
                    for (Object o : ab) {
                        parameters += o.toString() + ",";
                    }
                    break;
                }
            }
            if (parameters.length() > 0) {
                parameters = parameters.substring(0, parameters.length() - 1);
                parameters = "[" + parameters + "]";
            }

            logger.info("testName: " + testMethod.getMethodName() + parameters);

        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return testMethod.getMethodName() + parameters;
    }

    @AfterMethod
    public void afterMethod(ITestResult result) {

       // List<NameValuePair> params = new ArrayList<NameValuePair>();
/*//        请求属性
        params.add(new BasicNameValuePair("Url", xmAppApi.getUrl()));
        params.add(new BasicNameValuePair("RequestParams", xmAppApi.getApi_request_params().toString()));
        params.add(new BasicNameValuePair("RequestData", xmAppApi.getApi_request_data()));
//       测试报告添加caseOwner属性
        params.add(new BasicNameValuePair("CaseOwner", dal.getCase_owner()));
        params.add(new BasicNameValuePair("TraceId", xmAppApi.getApi_traceId()));
        if (xmAppApi.getApi_startTime() != null) {
            //        请求开始时间和结束时间
            params.add(new BasicNameValuePair("StartTime", new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(xmAppApi.getApi_startTime())));
        }
//        params.add(new BasicNameValuePair("EndTime",new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(xmAppApi.getApi_endTime())));
        Long expendTime = xmAppApi.getApi_requestTime();
        params.add(new BasicNameValuePair("ExpendTime", expendTime + "ms"));
        params.add(new BasicNameValuePair("Response", xmAppApi.getApi_response()));*/
        //result.setParameters(params.toArray());
        result.setAttribute("ApiDesc", xmAppApi.getApiDesc());
        //   请求属性
        result.setAttribute("Url", xmAppApi.getUrl());
        result.setAttribute("RequestParams", xmAppApi.getApi_request_params().toString());
        result.setAttribute("RequestData", xmAppApi.getApi_request_data());
//       测试报告添加caseOwner属性
        result.setAttribute("CaseOwner", dal.getCase_owner());
        result.setAttribute("TraceId", xmAppApi.getApi_traceId());
        if (xmAppApi.getApi_startTime() != null) {
            //        请求开始时间和结束时间
            result.setAttribute("StartTime", new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(xmAppApi.getApi_startTime()));
        }
//        params.add(new BasicNameValuePair("EndTime",new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(xmAppApi.getApi_endTime())));
        Long expendTime = xmAppApi.getApi_requestTime();
        result.setAttribute("ExpendTime", expendTime + "ms");
        result.setAttribute("Response", xmAppApi.getApi_response());


//        打印异常请求
        if (expendTime != null) {
            if (expendTime >= 500 && expendTime <= 1000) {
                LOGGER.warn(xmAppApi.getApiDesc() + "接口请求时间超过500毫秒 = " + expendTime.toString());
            } else if (expendTime > 1000) {
                LOGGER.error(xmAppApi.getApiDesc() + " 接口请求时间超过1秒 = " + expendTime.toString());
            }
        }

    }

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

    }
}
