package cn.pluss.platform.ys.impl;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.util.*;
import cn.pluss.platform.yinsheng.ReqEntity;
import cn.pluss.platform.yinsheng.ReqOldEntity;
import cn.pluss.platform.yinsheng.RespEntity;
import cn.pluss.platform.ys.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

/**
 * 银盛通用接口实现类
 *
 * @DATE 2021-06-21
 */
@Service("ysService")
@Slf4j
@RequiredArgsConstructor
public class YsServiceImpl implements YsService {

    private final RestTemplate restTemplate;

    private final YsConfig ysConfig;

    private final YsOldConfig ysOldConfig;

    @Override
    public JSONObject requestApi(String url, JSONObject reqData, String type) {
        try {
            ReqEntity request = new ReqEntity();
            if (YsService.TYPE_PAY.equals(type)) {
                request.setSrcMerchantNo(ysConfig.getSrcMerchantNo());
            } else {
                request.setAgentNo(ysConfig.getAgentNo());
            }
            request.setBizReqJson(reqData.toJSONString());
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            headers.add("User-Agent",
                    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");

            String signContent = SignUtils.getYSSignContent(JSONObject.parseObject(JSONObject.toJSONString(request)));

            request.setSign(RSAUtils.sign(ysConfig.getPriKey(), signContent));
            log.debug("请求报文==============>" + JSONObject.toJSONString(request));
            val multiValueMap = MapUtils.map2MultiValueMap((JSONObject) JSON.toJSON(request));

            HttpEntity<MultiValueMap<String, Object>> reqEntity = new HttpEntity<>(multiValueMap, headers);
            JSONObject responseJson = restTemplate.postForObject(url, reqEntity, JSONObject.class);

            if (responseJson == null) {
                throw new MsgException("请求失败，请求状态异常");
            }
            log.info(responseJson.toJSONString());
            return responseJson;

        } catch (Exception e) {
            e.printStackTrace();
            throw new MsgException("银盛接口异常");
        }
    }

    @Override
    public JSONObject requestApiCommon(String url, JSONObject reqData, String type) {
        try {
            ReqEntity request = new ReqEntity();
            if (YsService.TYPE_PAY.equals(type)) {
                request.setSrcMerchantNo(ysConfig.getSrcMerchantNo());
            } else {
                request.setAgentNo(ysConfig.getAgentNo());
            }
            request.setBizReqJson(reqData.toJSONString());
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            headers.add("User-Agent",
                    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");

            val bizContent = JSONObject.toJSONString(request);
            String signContent = SignUtils.getYSSignContent(JSONObject.parseObject(bizContent));

            request.setSign(RSAUtils.sign(ysConfig.getPriKey(), signContent));
            // 上传图片的请求参数不打印，日志太多了
            if (!url.equals(YsConfig.IMG_UPLOAD) && !url.equals(YsConfig.WX_AUTH)) {
                log.info("请求报文==============>" + bizContent);
            }

            log.info("请求地址：{}", url);
            val multiValueMap = MapUtils.map2MultiValueMap((JSONObject) JSON.toJSON(request));

//            if (url.equals(YsConfig.java.MER_AUDIT)) {
//                throw new MsgException("测试请求拦截");
//            }

            HttpEntity<MultiValueMap<String, Object>> reqEntity = new HttpEntity<>(multiValueMap, headers);
            RespEntity resp = restTemplate.postForObject(url, reqEntity, RespEntity.class);

            checkSign((JSONObject) JSON.toJSON(resp));

            if (resp == null) {
                throw new MsgException("请求失败，请求状态异常");
            }
            log.info(JSON.toJSONString(resp));

            if (!RespEntity.SUCCESS.equals(resp.getResponseCode())) {
                log.info(JSON.toJSONString(multiValueMap));
                throw new MsgException(resp.getResponseMeg());
            }

            return JSON.parseObject(resp.getBizResponseJson());
        } catch (Exception e) {
            e.printStackTrace();
            throw new MsgException("银盛接口异常");
        }
    }

    @Override
    public boolean checkSign(JSONObject responseData) throws Exception {
        String signContent = SignUtils.getYSSignContent(responseData);
        String sign = responseData.getString("sign");
        if (sign == null) {
            return true;
        }
        return RSAUtils.checkSign(ysConfig.getPubKey(), signContent, sign);
    }

    @Override
    public boolean checkSignOld(JSONObject responseData) throws Exception {
        String signContent = SignUtils.getYSSignContent(responseData);
        String sign = responseData.getString("signValue");
        return RSAUtils.checkSign(ysOldConfig.getOldPubKey(), signContent, sign);
    }

    /**
     * 旧版
     *
     * @param responseData
     * @param ysEnum
     * @return
     * @throws Exception
     */
    @Override
    public boolean oldCheckSign(JSONObject responseData, YsEnum ysEnum,String srcMerchantNo) {
        try {
            JSONObject respData = responseData.getJSONObject(ysEnum.getResponseParam());
            String sign = responseData.getString("sign");
            String signContent = SignUtils.getYSSignContent(respData);
            return RSAUtils.checkSign(ysConfig.getPubKeyVal(srcMerchantNo), signContent, sign);
        } catch (Exception e) {
            e.printStackTrace();
            MsgException.throwException("银盛接口签名异常！");
            return false;
        }
    }


    /**
     * 旧版银盛通用支付接口
     *
     * @param url
     * @param reqData
     * @param ysEnum
     * @return
     */
    @Override
    public JSONObject requestOldApiCommon(String url, JSONObject reqData, String type, YsEnum ysEnum,String srcMerchantNo) {
        return requestOldApiCommon(url, reqData, type, ysEnum, null,srcMerchantNo);
    }

    @Override
    public JSONObject requestOldApiCommon(String url, JSONObject reqData, String type, YsEnum ysEnum, Map<String, ByteArrayResource> fileMap,String srcMerchantNo) {
        try {
            ReqOldEntity request = new ReqOldEntity(reqData.getString(ReqOldEntity.VERSION_NAME));
            reqData.remove(ReqOldEntity.VERSION_NAME);
            request.setPartner_id(srcMerchantNo);
            request.setMethod(ysEnum.getApiName());
            request.setBiz_content(reqData.toJSONString());
            if (YsService.TYPE_PAY.equals(type)) {
                request.setNotify_url(ParametersUtil.domain + "/wap/notify/old/ysCallBack");
            }
            if(StringUtil.isNotEmpty(reqData.getString("returnUrl"))){
                request.setReturn_url(reqData.getString("returnUrl"));
                reqData.remove("returnUrl");
            }
            String signContent = SignUtils.getYSSignContent(JSONObject.parseObject(JSONObject.toJSONString(request)));
            log.info("========>【银盛】接口请求签名串为:{}<============", signContent);
            request.setSign(RSAUtils.sign(ysConfig.getPrikeyVal(srcMerchantNo), signContent));

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            headers.add("User-Agent",
                    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36");

            log.info("请求地址：{}", url);
            log.info("请求报文==============>:{}", JSONObject.toJSONString(request));

            val multiValueMap = MapUtils.map2MultiValueMap((JSONObject) JSON.toJSON(request));

            if (fileMap != null && !fileMap.isEmpty()) {
                for (Map.Entry<String, ByteArrayResource> entry : fileMap.entrySet()) {
                    multiValueMap.add(entry.getKey(), entry.getValue());
                }
            }

            HttpEntity<MultiValueMap<String, Object>> reqEntity = new HttpEntity<>(multiValueMap, headers);

            JSONObject resp = restTemplate.postForObject(url, reqEntity, JSONObject.class);

            if (resp == null) {
                throw new MsgException("请求失败，请求状态异常");
            }
            log.info("=========>【银盛】接口请求返回参数：{}<==================", resp.toJSONString());

            oldCheckSign(resp, ysEnum,srcMerchantNo);

            return resp.getJSONObject(ysEnum.getResponseParam());
        } catch (Exception e) {
            e.printStackTrace();
            throw new MsgException(e.getMessage());
        }
    }
}
