package com.izouma.nineth.utils.ikudot;

import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSONObject;
import com.anji.captcha.util.RandomUtils;
import com.izouma.nineth.config.IkudotpayProperties;
import com.izouma.nineth.exception.BusinessException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
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.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.struts.util.ResponseUtils;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.TreeMap;

@Slf4j
public class IkudotpayClient {

    private IkudotpayProperties ikudotpayProperties;

    private CloseableHttpClient httpClient;


    public IkudotpayClient(IkudotpayProperties ikudotpayProperties) {
        this.ikudotpayProperties = ikudotpayProperties;

        //构架客户端
        httpClient = HttpClientBuilder.create().build();

    }


    /**
     * 创建签名
     *
     */
    public String createSign(JSONObject commonWrapper){
        TreeMap sortedMap = new TreeMap<>();
        sortedMap.putAll(commonWrapper);
        List<String> signOriginal = new ArrayList<>();
        sortedMap.forEach((key, value) -> {
            if(!"sign".equals(key) && StringUtils.isNotEmpty(Objects.toString(value, ""))){
                signOriginal.add(key + "=" + value);
            }
        });

        signOriginal.add("secret_key=" + ikudotpayProperties.getSecretKey());

        String content = StringUtils.join(signOriginal, "&");
        //log.info("支付签名内容：" + content);
        String sign = DigestUtils.md5Hex(content);
        return sign.toUpperCase();
    }


    /**
     * 签名校验
     * @param commonWrapper
     * @param upSign
     * @return
     */
    private boolean verifySign(JSONObject commonWrapper, String upSign){
        String sign = createSign(commonWrapper);
        return sign.equals(upSign);
    }


    /**
     * 生成请求参数
     * @param params
     * @return
     */
    public JSONObject createRequestWrapper(JSONObject params){
        JSONObject commonWrapper = new JSONObject();
        //酷点聚合支付平台分配的商户编号
        commonWrapper.put("mch_id", ikudotpayProperties.getMerchId());
        //时间戳，格式为1541661668，精确到秒。服务端允许客户端请求最大时间误差为30分钟
        commonWrapper.put("timestamp", System.currentTimeMillis());
        //随机字符串，不长于32位
        commonWrapper.put("nonce_str", RandomUtils.getRandomString(16));
        //签名类型，默认填:MD5。(暂只支持MD5)
        commonWrapper.put("sign_type", "MD5");
        //请求参数的集合，最大长度不限，API请求Json转字符串格式。
        commonWrapper.put("content", params.toString());
        commonWrapper.put("sign", createSign(commonWrapper));

        return commonWrapper;

    }

    /**
     * 解析请求的数据
     * @param commonWrapper
     * @return
     */
    public JSONObject parseRequest(JSONObject commonWrapper){
        String upSign = commonWrapper.getString("sign");
        //签名校验
        boolean verify = verifySign(commonWrapper, upSign);
        if(!verify){
            throw new BusinessException("签名校验失败");
        }

        String resultStr = commonWrapper.getString("result");

        return JSONObject.parseObject(resultStr);
    }

    /**
     * 接口请求
     * @param tradePath
     * @param params
     * @return
     */
    public JSONObject postJson(String tradePath, JSONObject params){
        String url;
        if(tradePath.matches("^http(s?)://.+")){
            url  = tradePath;
        }else{
            url = StringUtils.stripEnd(ikudotpayProperties.getGateWay(), "/") + tradePath;
        }

        CloseableHttpResponse response = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            JSONObject requestData = createRequestWrapper(params);
            log.info("接口请求数据，地址：{}， 数据：{}", url, requestData);
            StringEntity bodyEntity = new StringEntity(requestData.toString(), ContentType.APPLICATION_JSON);
            httpPost.setEntity(bodyEntity);
            response = httpClient.execute(httpPost);
            String resStr = EntityUtils.toString(response.getEntity());
            log.info("接口请求响应结果：" + resStr);
            JSONObject resultJson = JSONObject.parseObject(resStr);
            String upSign = resultJson.getString("sign");


            //响应结果判断
            String code =  resultJson.getString("code");
            String msg = resultJson.getString("msg");
            if(!"0".equals(code)){
                throw new BusinessException(msg + "("+code+")");
            }

            //签名校验
            boolean verify = verifySign(resultJson, upSign);
            if(!verify){
                throw new BusinessException("签名校验失败");
            }

            String resultStr = resultJson.getString("result");

            return JSONObject.parseObject(resultStr);
        }catch(Exception e){
            String errorInfo = e.getMessage();
            if(StringUtils.isEmpty(errorInfo)){
                errorInfo = "接口未知错误";
            }
            throw new RuntimeException(errorInfo, e);
        }finally{
            if(response != null){
                EntityUtils.consumeQuietly(response.getEntity());
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }



}
