package com.bcxin.signature.util;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.bcxin.signature.util.common.StringUtil;
import com.google.common.collect.Lists;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/***
 * http请求工具类
 */
public class HttpUtils {

	private static final Logger logger = LoggerFactory.getLogger(ObjectToMapUtil.class);

	/****
	 *
	 * @param url
	 *            请求地址
	 * @param obj
	 *            实体类
	 * @return
	 */
	public static ResultJson sendHttp(String url, Object obj) {
		return sendHttp(url, obj, null);
	}
	private static final String CONTENT_TYPE_TEXT_JSON = "text/json";
	private static final String APPLICATION_JSON = "application/json";


	/***
	 * 参数json字符串的post方法
	 * @param url
	 * @param json
	 * @return
	 */
	public static String postJsonString(String url, String json) {
		try (CloseableHttpClient httpclient = HttpClients.createDefault()){
			HttpPost httppost = new HttpPost(url);
			httppost.addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);
			if(StringUtil.isNotEmpty(json)){
				StringEntity se = new StringEntity(json,StandardCharsets.UTF_8);
				se.setContentType(CONTENT_TYPE_TEXT_JSON);
				se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON));
				httppost.setEntity(se);
			}
			try (CloseableHttpResponse response = httpclient.execute(httppost) ){
				HttpEntity entity = response.getEntity();
				if (entity != null) {
					return EntityUtils.toString(entity, StandardCharsets.UTF_8);
				}
			}
		} catch (IOException e) {
			logger.error(e.getMessage(),e);
		}
		return "";
	}

	/****
	 *
	 * @param url
	 *            请求地址
	 * @param obj
	 *            参数对象
	 * @param clazz
	 *            实体类
	 * @return
	 */
	public static ResultJson sendHttp(String url, Object obj, Class clazz) {
		// //object 转map
		Map<String, Object> paramMap = (obj == null ? null : ObjectToMapUtil.ObjectToMap(obj));
		ResultJson resultJson = new ResultJson();
		try {
			logger.info("参数: "+paramMap.toString());
			String result = doPost(url, paramMap);
			if(!JSONUtil.isJson(result)){
				resultJson.setSuccessful(false);
				resultJson.setData(result);
				resultJson.setMsg(result);
				return resultJson;
			}
			JSONObject jsonback = JSONUtil.parseObj(result);
			logger.info("结果: "+jsonback.toString());
			if (Boolean.valueOf(String.valueOf(jsonback.get("successful")))) {
				resultJson.setSuccessful(true);
			}else{
				resultJson.setSuccessful(false);
			}
			resultJson.setData(jsonback.get("data"));

			if (jsonback.get("msg") != null && !"null".equals(jsonback.get("msg").toString())) {
				resultJson.setMsg(jsonback.get("msg").toString());
			} else {
				resultJson.setMsg("");
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		return resultJson;
	}

	/**
	 * <b> Map<String, String>解析成List<NameValuePair> </b>
	 * @author ZXF
	 * @create 2019/06/27 0027 10:56
	 * @version
	 * @注意事项 </b>
	 */
	public static ResultJson pairSendHttp(String url, Map<String, String> data) {
		// //object 转map
		ResultJson resultJson = new ResultJson();
		try {
			logger.info("开始请求接口地址:" + url);
			logger.info("参数: "+data.toString());
			List<NameValuePair> pairList = Lists.newArrayList();
			if (MapUtil.isNotEmpty(data)) {
				Iterator iterator = data.entrySet().iterator();
				while(iterator.hasNext()){
					Map.Entry<String,String> elem = (Map.Entry<String, String>) iterator.next();
					pairList.add(new BasicNameValuePair(elem.getKey(),elem.getValue()));
				}
			}
			String result = doPost(url, pairList);
			if(StringUtil.isEmpty(result)){
				resultJson.setSuccessful(false);
				resultJson.setMsg("返回报文为空！");
				return resultJson;
			}
			JSONObject jsonback = JSONUtil.parseObj(result);
			logger.info("参数: "+jsonback.toString());
			if (Boolean.valueOf(String.valueOf(jsonback.get("successful")))) {
				resultJson.setSuccessful(true);
			}else{
				resultJson.setSuccessful(false);
			}
			resultJson.setData(jsonback.get("data"));

			if (jsonback.get("msg") != null && !"null".equals(jsonback.get("msg").toString())) {
				resultJson.setMsg(jsonback.get("msg").toString());
			} else {
				resultJson.setMsg("");
			}
			logger.info("结束请求接口地址:" + url);
		} catch (Exception e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		return resultJson;
	}


	public static Result sendHttpRt(String url, Map map) {
		//object 转map
//		Map<String, Object> paramMap = (obj == null ? null : ObjectToMapUtil.ObjectToMap(obj));
		Result ret = Result.fail("接口返回空");
		try {
			logger.info("开始请求接口地址:" + url);
			logger.info("请求报文: "+map.toString());
			String result = doPost(url, map);
			if(StringUtil.isNotEmpty(result)){
				logger.info("返回报文: "+result);
				ret = JSONUtil.toBean(result,Result.class);
			}
			logger.info("结束请求接口地址:" + url);
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			e.printStackTrace();
			ret = Result.fail(e.getMessage());
		}
		return ret;
	}

	/****
	 *
	 * @param url
	 *            请求地址
	 * @param paramMap
	 *            实体类
	 * @return
	 */
	public static ResultJson sendHttpMap(String url, Map<String, Object> paramMap) {
		// //object 转map
		ResultJson resultJson = new ResultJson();
		try {
			String result = doPost(url, paramMap);
			if (StringUtil.isEmpty(result)){
				resultJson.setSuccessful(false);
				resultJson.setMsg("未获取到数据");
				return resultJson;
			}

			JSONObject jsonback = JSONUtil.parseObj(result);
			logger.info("参数: "+jsonback.toString());
			if (Boolean.valueOf(String.valueOf(jsonback.get("successful")))) {
				resultJson.setSuccessful(true);
			}else{
				resultJson.setSuccessful(false);
			}
			resultJson.setData(jsonback.get("data"));
			if (jsonback.get("msg") != null && !"null".equals(jsonback.get("msg").toString())) {
				resultJson.setMsg(jsonback.get("msg").toString());
			} else {
				resultJson.setMsg("");
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		return resultJson;
	}

	/**
	 * SAAS调用百课堂服务接口专用
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 */
	public static ResultJson sendHttpMapForTrain(String url, Map<String, Object> paramMap) {
		// //object 转map
		ResultJson resultJson = new ResultJson();
		try {
			String result = doPost(url, paramMap);
			JSONObject jsonback = JSONUtil.parseObj(result);
			if (jsonback.get("retType") != null && !ObjectUtil.equal(jsonback.get("retType"),"-1")) {
				resultJson.setSuccessful(true);
			}else{
				resultJson.setSuccessful(false);
			}
			resultJson.setData(jsonback.get("data"));
			if (jsonback.get("msg") != null && !"null".equals(jsonback.get("msg").toString())) {
				resultJson.setMsg(jsonback.get("msg").toString());
			} else {
				resultJson.setMsg("");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			e.printStackTrace();
		}
		return resultJson;
	}


	/**
	 * SAAS调用百课堂服务接口专用
	 *
	 * @param url
	 * @param params
	 * @return
	 */
	public static ResultJson sendHttpPairForTrain(String url, List<NameValuePair> params) {
		// //object 转map
		ResultJson resultJson = new ResultJson();
		try {
			String result = doPost(url, params);
			JSONObject jsonback = JSONUtil.parseObj(result);
			if (jsonback.get("retType") != null && !ObjectUtil.equal(jsonback.get("retType"),"-1") ) {
				resultJson.setSuccessful(true);
			}else{
				resultJson.setSuccessful(false);
			}
			resultJson.setData(jsonback.get("data"));
			if (jsonback.get("msg") != null && !"null".equals(jsonback.get("msg").toString())) {
				resultJson.setMsg(jsonback.get("msg").toString());
			} else {
				resultJson.setMsg("");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			e.printStackTrace();
		}
		return resultJson;
	}

	/**
	 * 发送POST请求，UTF8格式
	 * 
	 * @param url
	 * @param params
	 * @param url
	 * @return
	 */
	public static String doPost(String url, List<NameValuePair> params, int timeout) {
		String result = null;
		try (CloseableHttpClient httpClient = HttpClients.createDefault()){
			HttpPost httpPost = new HttpPost(url);
			RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeout).setSocketTimeout(timeout)
					.build();
			httpPost.setConfig(requestConfig);
			httpPost.setEntity(new UrlEncodedFormEntity(params, StandardCharsets.UTF_8));
			try (CloseableHttpResponse resp = httpClient.execute(httpPost)) {
				HttpEntity entity = resp.getEntity();
				result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
			}
			logger.debug("返回结果：[{}]", result);
			logger.debug("--------结束http请求--------");
		} catch (Exception ex) {
			logger.error(ex.getMessage(),ex);
		}
		return result;
	}


	/**
	 * 发送POST请求，UTF8格式
	 *
	 * @param url
	 * @param params
	 * @param url
	 * @return
	 */
	public static String doPost(String url, List<NameValuePair> params) {
		String result = null;
		try (CloseableHttpClient httpClient = HttpClients.createDefault()){
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new UrlEncodedFormEntity(params, StandardCharsets.UTF_8));
			try (CloseableHttpResponse resp = httpClient.execute(httpPost)) {
				HttpEntity entity = resp.getEntity();
				result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
			}
			logger.debug("返回结果：[{}]", result);
			logger.debug("--------结束http请求--------");
		} catch (Exception ex) {
			logger.error(ex.getMessage(),ex);
		}
		return result;
	}

	/**
	 * 
	 * @param url
	 * @param map
	 * @return
	 */
	public static String doPost(String url, Map<String, Object> map) {
		String result = null;
		try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
			HttpPost httpPost = new HttpPost(url);
			String charset = "utf-8";
			int timeout = 60000;
			RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeout).setSocketTimeout(timeout)
					.build();
			httpPost.setConfig(requestConfig);
			// 设置参数
			List<NameValuePair> list = new ArrayList<NameValuePair>();
			// 遍历map集合
			for (Map.Entry<String, Object> entry : map.entrySet()) {
				list.add(new BasicNameValuePair(entry.getKey(),
						entry.getValue() == null ? "" : entry.getValue().toString()));
			}
			if (list.size() > 0) {
				// charset=utf-8
				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, charset);
				httpPost.setEntity(entity);
			}
			HttpResponse response = httpClient.execute(httpPost);
			if (response != null) {
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					result = EntityUtils.toString(resEntity, charset);
				}
			}
		} catch (Exception ex) {
			logger.error("====== URL:"+url);
			logger.error("====== PARAM:"+map.toString());
			logger.error("====== ERROR:"+ex.getMessage());
			ex.printStackTrace();
		}
		return result;
	}


	/**
	 * 发送get请求，UTF8格式(针对特殊字符转码)
	 *
	 * @param strUrl
	 * @param params
	 * @author llc
	 * @date 2020-07-31
	 * @return
	 */
	public static String doGet(String strUrl, List<NameValuePair> params) {
		String result = null;
		try (CloseableHttpClient httpClient = HttpClients.createDefault()){
			URL url = new URL(strUrl);
			URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null);
			HttpGet HttpGet = new HttpGet(uri);
			try (CloseableHttpResponse resp = httpClient.execute(HttpGet)) {
				HttpEntity entity = resp.getEntity();
				result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
			}
		} catch (Exception ex) {
		}
		return result;
	}
}
