package com.qunzhixinxi.hnqz.common.ding.entity;

import com.qunzhixinxi.hnqz.common.ding.utils.HttpClientUtils;
import io.micrometer.core.instrument.util.StringUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.jasypt.contrib.org.apache.commons.codec_1_3.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class Test {


	public static void main(String[] args) throws Exception {

		/**
		 * 参数列表
		 */

		String bodyStr = "{\n" +
				"    \"freelances\": [\n" +
				"      {\n" +
				"        \"mobile\": \"15000998877\",\n" +
				"        \"name\": \"张三\",\n" +
				"        \"idType\": \"1\",\n" +
				"        \"idCard\": \"350198765623418765\"\n" +
				"      }\n" +
				"    ]\n" +
				"}";
		String serviceSign = serviceSign("/oapi/v1/employ/freelances/check",
				"POST", new HashMap<>(), bodyStr.getBytes());
		System.out.println("serviceSign=========" + serviceSign);
		// 创建一个post对象
		String url = "https://test-f.renlijia.com/oapi/v1/employ/freelances/check";
		HttpPost post = new HttpPost(url);

		StringEntity s = new StringEntity(bodyStr, "UTF-8"); // 中文乱码在此解决
		s.setContentType("application/json");
		post.setEntity(s);
		post.setHeader("app-id","888999");
		post.setHeader("signature",serviceSign);

		// 执行post请求
		CloseableHttpResponse response = HttpClients.createDefault().execute(post);
//		String json = HttpClientUtils.doPost("https://test-f.renlijia.com", params);

		String result = fromStream(response.getEntity().getContent(), "UTF-8");
		System.out.println("result-----" + result);

		System.out.println("response=========" + response.getStatusLine().getStatusCode());
		System.out.println("response=========" + response.getEntity().getContent().toString());
	}

	private static String fromStream(InputStream is, String charset) throws IOException {
		BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
		StringBuffer buffer = new StringBuffer();

		String line = "";
		while ((line = in.readLine()) != null) {
			buffer.append(line);
		}

		return new String(buffer.toString().getBytes("UTF-8"), charset);
	}


	/**
	 * 签名算法HmacSha256
	 */
	public static final String HMAC_SHA256 = "HmacSHA256";

	/**
	 * 编码
	 */
	public static final String ENCODING = "UTF-8";
	/**
	 * 换⾏符
	 */
	private static char LF = '\n';

	private static final String HTTP_METHOD_POST = "post";
	private static final String HTTP_METHOD_PUT = "put";

	/**
	 * 26 * 获取请求签名
	 * 27 *
	 * 28 * @param uri 原始HTTP请求PATH（例：/oapi/v1/employ/free
	 * lances/check）
	 * 29 * @param httpMethod 原始HTTP请求⽅法（例：POST）5
	 * 30 * @param paramsMap 原始HTTP请求所有Query+Form参数（POST请求：Ma
	 * ps.newHashMap()）
	 * 31 * @param body 原始HTTP请求Body体（仅当请求为POST/PUT且⾮表
	 * 单请求才需要设置此属性,表单形式的需要将参数放到paramsMap中）
	 * 32 * @param appId ⽤户id
	 * 33 * @return 签名结果
	 * 34 * @throws Exception
	 * 35
	 */

	public static String serviceSign(String uri, String httpMethod, Map<String, Object> paramsMap, byte[] body) throws Exception {
		String bodyMd5 = buildBodyMd5(httpMethod, body);
		String resourceToSign = buildResource(uri, paramsMap);
		String stringToSign = buildStringToSign(resourceToSign,
				httpMethod, bodyMd5);

		Mac hmacSha256 = Mac.getInstance(HMAC_SHA256);
		String appSecret = "5T8134269D467IGa0ZC7s907666r2C43";
		byte[] keyBytes = appSecret.getBytes(ENCODING);
		hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.
				length, HMAC_SHA256));
		return new String(Base64.encodeBase64(hmacSha256.doFinal
				(stringToSign.getBytes(ENCODING))), ENCODING);
	}


	public static String buildBodyMd5(String httpMethod, byte[] body) throws IOException {
		if (body == null) {
			return null;
		}
		if (!httpMethod.equalsIgnoreCase(HTTP_METHOD_POST) && !httpMethod.equalsIgnoreCase(HTTP_METHOD_PUT)){
			return null;
		}
		InputStream inputStream = new ByteArrayInputStream(body);
		byte[] bodyBytes = IOUtils.toByteArray(inputStream);
		if (bodyBytes != null && bodyBytes.length > 0) {
			return base64AndMD5(bodyBytes).trim();
		}
		return null;
	}

	public static String base64AndMD5(byte[] bytes) {
		try {
			final MessageDigest md = MessageDigest.getInstance(
					"MD5");
			md.reset();
			md.update(bytes);
			final Base64 base64 = new Base64();
			return new String(base64.encode(md.digest()));
		} catch (final NoSuchAlgorithmException e) {
			throw new IllegalArgumentException("unknown algorith m MD5");
		}
	}

	public static String buildResource(String uri, Map<String, Object> paramsMap) {
		StringBuilder builder = new StringBuilder();
		builder.append(uri);
		TreeMap<String, Object> sortMap = new TreeMap<>();
		sortMap.putAll(paramsMap);
		if (sortMap.size() > 0) {
			builder.append('?');
			builder.append(buildMapToSign(sortMap));
		}
		return builder.toString();
	}

	public static String buildStringToSign(String resourceToSign, String method, String bodyMd5) {
		StringBuilder sb = new StringBuilder();
		sb.append(method).append(LF);
		if (StringUtils.isNotBlank(bodyMd5)) {
			sb.append(bodyMd5);
		}
		sb.append(LF);
		sb.append(resourceToSign);
		return sb.toString();
	}

	/**
	 * 将Map转换为用&及=拼接的字符串
	 */
	public static String buildMapToSign(Map<String, Object> paramMap) {
		StringBuilder builder = new StringBuilder();

		for (Map.Entry<String, Object> e : paramMap.entrySet()) {
			if (builder.length() > 0) {
				builder.append('&');
			}
			String key = e.getKey();
			Object value = e.getValue();
			if (value != null) {
				if (value instanceof List) {
					List list = (List) value;
					if (list.size() == 0) {
						builder.append(key);
					} else {
						builder.append(key).append("=").append(String.valueOf(list.get(0)));
					}
				} else if (value instanceof Object[]) {
					Object[] objs = (Object[]) value;
					if (objs.length == 0) {
						builder.append(key);
					} else {
						builder.append(key).append("=").append(String.valueOf(objs[0]));
					}
				} else {
					builder.append(key).append("=").append(String.valueOf(value));
				}
			}
		}
		return builder.toString();
	}


	public void check() throws IOException {

		String resourceToSign = "/oapi/v1/employ/freelances/check";
		String body ="{\"freelances\":[{\"mobile\":\"15000998877\",\"name\":\"张三\",\"idType\":\"1\",\n" +
				"\"idCard\":\"350198765623418765\"}]}";

		String bodyMd5 = buildBodyMd5(HTTP_METHOD_POST, body.getBytes());

		String stringToSign = buildStringToSign(resourceToSign, HTTP_METHOD_POST, bodyMd5);
	}
}
