package com.friday.custody.service.trustService.csc.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import javax.net.ssl.*;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Slf4j
public class TestHttpUtil {
	private static SSLSocketFactory ssf = null;
	static {
		try {
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());

			ssf = sslContext.getSocketFactory();

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private static class MyX509TrustManager implements X509TrustManager {

		MyX509TrustManager() throws Exception {

		}

		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

		}

		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

		}

		public X509Certificate[] getAcceptedIssuers() {

			return null;
		}
	}

	public static String httpsRequest(String url, String msg, boolean isPost) {
		try {

			URL myURL = new URL(url);
			HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();
			httpsConn.setSSLSocketFactory(ssf);
			httpsConn.setHostnameVerifier(new HostnameVerifier() {
				@Override
				public boolean verify(String arg0, SSLSession arg1) {
					return true;
				}
			});
			httpsConn.setRequestMethod(isPost ? "POST" : "GET");
			httpsConn.setRequestProperty("Content-Type", "application/json");;
			if (msg != null) {

				httpsConn.setDoOutput(true);
				OutputStreamWriter osw = new OutputStreamWriter(httpsConn.getOutputStream(), "UTF-8");
				osw.write(msg);
				osw.flush();
			}

			InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream(), "UTF-8");
			StringBuilder sb = new StringBuilder();

			int respInt = insr.read();
			while (respInt != -1) {
				sb.append((char) respInt);
				respInt = insr.read();
			}

			return sb.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * 向指定URL发送GET方法的请求
	 * 
	 * @param url 发送请求的URL
	 * 
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGet(String url) {
		String result = "";
		BufferedReader in = null;
		try {
			String urlNameString = url;
			URL realUrl = new URL(urlNameString);
			// 打开和URL之间的连接
			URLConnection connection = realUrl.openConnection();
			// 设置通用的请求属性
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 建立实际的连接
			connection.connect();
			// 获取所有响应头字段
			Map<String, List<String>> map = connection.getHeaderFields();
			// 遍历所有的响应头字段
			for (String key : map.keySet()) {
				System.out.println(key + "--->" + map.get(key));
			}
			// 定义 BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送GET请求出现异常！" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输入流
		finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 * 
	 * @param url  发送请求的 URL
	 * @param body
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String body) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			conn.setRequestProperty("Content-Type", "application/json");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送body
			out.print(body);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常！" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	public static String createSign(String method, String serviceId, List<String> pms, String apiSecret,
			String postbody) {
		StringBuilder sb = new StringBuilder(method).append(serviceId);
		Collections.sort(pms);
		sb.append(StringUtils.join(pms, ""));
		if (postbody != null && "POST".equals(method)) {
			sb.append(postbody);
		}
		sb.append(apiSecret);
		System.out.println("sb.tostr: " + sb.toString());
		try {
			String str = URLEncoder.encode(sb.toString(), "UTF-8");
			System.out.println("str: " + str);
			return getMD5(str);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	public static String byte2hex(byte[] data) {
		StringBuffer sb = new StringBuffer();
		int len = data.length;
		for (int i = 0; i < len; i++) {
			String temp = Integer.toHexString(((int) data[i]) & 0xFF);
			for (int t = temp.length(); t < 2; t++) {
				sb.append("0");
			}
			sb.append(temp);
		}
		String s = sb.toString();
		if(StringUtils.isNotBlank(s)){
			return s;
		}
		return null;

	}

	public static String getMD5(String str) {
		MessageDigest messageDigest = null;
		byte[] byteArray = null;

		try {
			messageDigest = MessageDigest.getInstance("MD5");

			messageDigest.reset();

			messageDigest.update(str.getBytes("UTF-8"));
			byteArray = messageDigest.digest();
			String byte2hex = byte2hex(byteArray);
			if(StringUtils.isNotBlank(byte2hex)){
				return byte2hex;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 不需要用户授权的API接口调用
	 */
	public static String callNoAuthFunc(String url, Map<String, Object> urlParams, String body, boolean isPost,
			boolean isSecure, String apiSecret, String apiKey) {
		try {
			TimeUnit.SECONDS.sleep(2L);
		} catch (InterruptedException e) {
			log.info("中信建投每两秒调一次接口终止");
			e.printStackTrace();
			Thread.currentThread().interrupt();
		}
		String servicePath = url.substring(url.indexOf("/rest"));
		System.out.print("test"+servicePath);;
		// 共通参数包括apikey、ts、sign
		long t = System.currentTimeMillis();
		// GET调用
		// 除了sign外所有参数用来计算sign
		final List<String> paramStrings = new ArrayList<String>();
		List<String> encodeParams = new LinkedList<>();
		if (urlParams != null) {
			urlParams.forEach((k, v) -> {
				if (v != null) {
					paramStrings.add(k + "=" + v);
					try {
						encodeParams.add(k + "=" + URLEncoder.encode(v.toString(), "UTF-8"));
					} catch (Exception e) {
						e.printStackTrace();
					}

				}

			});
		}

		paramStrings.add("ts=" + t);
		paramStrings.add("apikey=" + apiKey);

		// 计算签名sign
		String sign = createSign(isPost ? "POST" : "GET", servicePath, paramStrings, apiSecret, null);
		String parampre = encodeParams.size() > 0 ? StringUtils.join(encodeParams, "&") + "&" : "";
		String requrl = url + "?" + parampre + "ts=" + t + "&apikey=" + apiKey + "&sign=" + sign;
		System.out.print(isPost ? "POST-->" : "GET -->");
		System.out.println("URL: " + requrl);
		String rv = null;
		if (isPost) {
			// post

			if (isSecure) {
				rv = TestHttpUtil.httpsRequest(requrl, body, true);
			} else {
				rv = TestHttpUtil.sendPost(requrl, body);
			}

		} else {
			// get
			// GET方法最终的url

			if (isSecure) {
				rv = TestHttpUtil.httpsRequest(requrl, null, false);
			} else {
				rv = TestHttpUtil.sendGet(requrl);
			}
		}

		return rv;

	}

}
