package org.springblade.payment.cmcc.util;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.common.utils.SpringContextHolder;
import org.springblade.core.log.logger.BladeLogger;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.payment.cmcc.config.CmccPointConfig;
import org.springblade.payment.cmcc.enums.CmccResponseStatus;
import org.springblade.payment.cmcc.exception.CmccRequestException;
import org.springblade.payment.cmcc.request.CmccDectOrderRequest;
import org.springblade.payment.cmcc.request.CmccPlaceOrderRequest;
import org.springblade.payment.cmcc.request.CmccRequest;
import org.springblade.payment.cmcc.response.CmccResponse;

import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: Silent
 * @Description 移动对接工具
 * @Date: Created in 11:43 2021/11/11
 * @Modified By:
 */
public class CmccUtil {
	/**
	 * 日志
	 */
	private static final BladeLogger logger = SpringContextHolder.getBean(BladeLogger.class);

	/**
	 * cmcc配置
	 */
	private static final CmccPointConfig cmccPointConfig = SpringContextHolder.getBean(CmccPointConfig.class);

	/**
	 * 日期时间格式
	 */
	private static final SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyyMMddHHmmss");


	/**
	 * 生成签名
	 *
	 * @param values
	 * @return
	 */
	private static String generate(List<String> values) {
		if (ObjectUtils.isEmpty(values)) {
			return null;
		}

		//删除null值
		while (values.remove(null)) {
		}

		//排序、拼接
		Collections.sort(values);
		StringBuilder sb = new StringBuilder();
		for (String value : values) {
			if (value != null && StringUtils.isNotEmpty(value)) {
				sb.append(value);
			}
		}
		return DigestUtil.md5Hex(sb.toString().getBytes(StandardCharsets.UTF_8));
	}

	/**
	 * 签名
	 *
	 * @param cmccRequest 请求参数
	 */
	private static <T extends CmccRequest> T sign(T cmccRequest) {
		//转化为参数
		Map<String, Object> stringObjectMap = BeanUtil.toMap(cmccRequest);
		//参数集合
		Set<String> param = new TreeSet<>();
		for (Map.Entry<String, Object> stringObjectEntry : stringObjectMap.entrySet()) {
			//排除空值和请求号
			if (ObjectUtils.isNotEmpty(stringObjectEntry.getValue())) {
				param.add((String) stringObjectEntry.getValue());
			}
		}
		//添加SignKey
		param.add(cmccPointConfig.getSignKey());
		String paramValue = ArrayUtil.join(param.toArray(), "");
		logger.warn("CMCC-排序后参数", paramValue);
		//进行签名
		cmccRequest.setSign(SecureUtil.md5(paramValue));
//		cmccRequest.setCheckType("01");
//		cmccRequest.setSign(SecureUtil.md5(cmccRequest.getRequestId()+cmccPointConfig.getSignKey()));
		logger.warn("CMCC-签名后参数", JSONObject.toJSONString(cmccRequest));
		return cmccRequest;
	}

	/**
	 * 添加参数
	 *
	 * @param cmccRequest
	 * @param callback
	 */
	private static <T extends CmccRequest> T checkParam(T cmccRequest, boolean callback) {
		cmccRequest.setPartnerId(cmccPointConfig.getPartnerId());
		cmccRequest.setStoreId(cmccPointConfig.getStoreId());
		//判断reuqestId是否为空
		if (StringUtils.isEmpty(cmccRequest.getRequestId())) {
			cmccRequest.setRequestId(IdUtil.randomUUID());
		}
		//判断reqTime是否为空
		if (StringUtils.isEmpty(cmccRequest.getReqTime())) {
			cmccRequest.setReqTime(dateTimeFormat.format(DateUtil.now()));
		}
		//设置回调地址
		if (callback) {
			cmccRequest.setCallbackUrl(cmccPointConfig.getCallbackUrl());
		}
		return cmccRequest;
	}

	/**
	 * 查询移动积分
	 *
	 * @param cmccRequest
	 * @return
	 */
	public static CmccResponse queryCmccBalance(CmccRequest cmccRequest) throws CmccRequestException {
		if (ObjectUtils.isEmpty(cmccRequest) || StringUtils.isEmpty(cmccRequest.getMobile())) {
			throw new CmccRequestException("参数不能为空");
		}
		return sendCmccRequest(cmccRequest, "/api/kb/queryCmccBalance", true);
	}

	/**
	 * 移动积分订单创建
	 *
	 * @param cmccPlaceOrderRequest
	 * @return
	 */
	public static CmccResponse placeOrder(CmccPlaceOrderRequest cmccPlaceOrderRequest) throws CmccRequestException {
		if (ObjectUtils.isEmpty(cmccPlaceOrderRequest) || StringUtils.isEmpty(cmccPlaceOrderRequest.getMobile())
			|| StringUtils.isEmpty(cmccPlaceOrderRequest.getOutOrderId()) || StringUtils.isEmpty(cmccPlaceOrderRequest.getPoints())
			|| StringUtils.isEmpty(cmccPlaceOrderRequest.getSessionId()) || StringUtils.isEmpty(cmccPlaceOrderRequest.getFingerprint())
			|| ObjectUtils.isEmpty(cmccPlaceOrderRequest.getProductItemList()) || ObjectUtils.isEmpty(cmccPlaceOrderRequest.getProductItemList())) {
			throw new CmccRequestException("参数不能为空");
		}
		return sendCmccRequest(cmccPlaceOrderRequest, "/api/kb/placeOrder", false);
	}

	/**
	 * 移动发送短信
	 *
	 * @param cmccPlaceOrderRequest
	 * @return
	 */
	public static CmccResponse sendCmccSms(CmccPlaceOrderRequest cmccPlaceOrderRequest) throws CmccRequestException {
		if (ObjectUtils.isEmpty(cmccPlaceOrderRequest) || StringUtils.isEmpty(cmccPlaceOrderRequest.getMobile())
			|| StringUtils.isEmpty(cmccPlaceOrderRequest.getOutOrderId())) {
			throw new CmccRequestException("参数不能为空");
		}
		//设置请求
		return sendCmccRequest(cmccPlaceOrderRequest, "/api/kb/sendCmccSms", false);
	}

	/**
	 * 订单支付接口
	 *
	 * @param cmccDectOrderRequest
	 * @return
	 */
	public static CmccResponse dectOrder(CmccDectOrderRequest cmccDectOrderRequest) throws CmccRequestException {
		if (ObjectUtils.isEmpty(cmccDectOrderRequest) || StringUtils.isEmpty(cmccDectOrderRequest.getMobile())
			|| StringUtils.isEmpty(cmccDectOrderRequest.getOutOrderId()) || StringUtils.isEmpty(cmccDectOrderRequest.getSmsCode())
			|| StringUtils.isEmpty(cmccDectOrderRequest.getSessionId()) || StringUtils.isEmpty(cmccDectOrderRequest.getFingerprint())
			|| StringUtils.isEmpty(cmccDectOrderRequest.getMachinetype())) {
			throw new CmccRequestException("参数不能为空");
		}
		return sendCmccRequest(cmccDectOrderRequest, "/api/kb/dectOrder", false);
	}

	/**
	 * 发送CMCC请求
	 *
	 * @param cmccRequest 请求
	 * @param url         地址
	 * @param callback    是否需要回调
	 * @return
	 * @throws CmccRequestException
	 */
	private static CmccResponse sendCmccRequest(CmccRequest cmccRequest, String url, boolean callback) throws CmccRequestException {
		//进行签名
		sign(checkParam(cmccRequest, callback));
		//设置请求
		HttpResponse httpResponse = HttpRequest.post(new StringBuilder(cmccPointConfig.getUrl()).append(url).toString())
			//添加参数，进行签名
			.body(JSONObject.toJSONString(cmccRequest)).execute();

		logger.info("CMCC-请求响应内容", httpResponse.body());
		JSONObject jsonObject = JSONObject.parseObject(httpResponse.body());
		CmccResponse cmccResponse;
		if (ObjectUtils.isNotEmpty(jsonObject.get("respCode"))) {
			cmccResponse = CmccResponse
				.builder()
				.resultCode(jsonObject.getString("respCode"))
				.message(jsonObject.getString("respMsg"))
				.requestId(jsonObject.getString("requestId"))
				.data(jsonObject.getString("data"))
				.build();
		} else {
			cmccResponse = jsonObject.toJavaObject(CmccResponse.class);
		}
		//判断状态是否成功
		if (!StringUtils.equals(cmccResponse.getResultCode(), CmccResponseStatus.SUCCESS.getCode())
			&& (!callback || !StringUtils.equals(cmccResponse.getResultCode(), CmccResponseStatus.AUTH.getCode()))) {
			throw new CmccRequestException(cmccResponse.getMessage());
		}
		return cmccResponse;
	}
}
