package cn.pluss.platform.ys.impl.v20210929;

import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.symmetric.DES;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.util.MapUtils;
import cn.pluss.platform.util.RSAUtils;
import cn.pluss.platform.util.SignUtils;
import cn.pluss.platform.yinsheng.v20210929.ReqEntity;
import cn.pluss.platform.yinsheng.v20210929.ReqMethod;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Service("ysServiceV2")
public class YsServiceV2 {

    @Autowired
    private YsConfigV2 ysConfig;

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 只用于新的进件接口
     *
     * @param url       请求链接
     * @param reqMethod 请求方法
     * @param reqData   请求参数
     * @return
     */
    public JSONObject req(String url, ReqMethod reqMethod, JSONObject reqData) {

        try {
            ReqEntity request = new ReqEntity(reqMethod);
            request.setSrc(ysConfig.getSrc());

            request.setData(reqData.toJSONString());
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            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("业务参数==============>" + JSONObject.toJSONString(reqData));
            DES des = new DES(ysConfig.getEncryptPwd().getBytes(StandardCharsets.UTF_8));
            String s = des.encryptBase64(request.getData());
            request.setData(s);
            String encryptOriginData = SignUtils.getSignContent((JSONObject) JSON.toJSON(request));
            log.info("加签源数据==============>" + encryptOriginData);
            request.setSignValue(RSAUtils.sign(ysConfig.getPriKeyV2(), encryptOriginData));

            request.setReqFlowId("YS" + System.currentTimeMillis() % 10000000 + UUID.randomUUID().toString().substring(4, 7));
            // 上传图片的请求参数不打印，日志太多了
            if (!url.equals(YsConfigV2.IMG_UPLOAD)) {
                log.warn("请求报文==============>" + JSONObject.toJSONString(request));
            }

            log.info("请求地址：{}", url);

            HttpEntity<JSONObject> reqEntity = new HttpEntity<>((JSONObject) JSON.toJSON(request), headers);
            String respStr = restTemplate.postForObject(url, reqEntity, String.class);
            log.info(respStr);

            JSONObject result = JSON.parseObject(respStr);
            try {
                Object signValue = result.remove("signValue");
                String decryptOriginData = result.toJSONString();
                RSAUtils.checkSign(ysConfig.getPriKeyV2(), decryptOriginData, signValue.toString());
            } catch (Exception e) {
                log.error("返回参数验签异常");
            }
            JSONObject data = result.getJSONObject("data");
            if (data == null) {
                throw new MsgException("接口未获取到业务信息");
            }

            if (!data.getString("code").equals(YsConstant.ReqStatus.SUCCESS.getCode())
                    && !"商户为非法人结算，需要人工审核".equals(data.getString("note"))) {
                throw new MsgException(data.getString("note"));
            }

            return data;
        } catch (Exception e) {
//            e.printStackTrace();
            if (e instanceof MsgException) {
                throw (MsgException) e;
            } else {
                throw new MsgException("银盛接口异常, {}", e.getMessage());
            }
        }
    }

    /**
     * 只用于新的进件接口
     *
     * @param url       请求链接
     * @param method    请求方法
     * @param reqData   请求参数
     * @param extraBase 额外的基本参数
     * @return
     */
    public JSONObject req(String url, String method, JSONObject reqData, Map<String, Object> extraBase, Map<String, Object> fileMap) {

        try {
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("method", method);
            paramMap.put("partner_id", ysConfig.getSrcMerchantNo());
            paramMap.put("timestamp", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            paramMap.put("charset", "utf-8");
            paramMap.put("sign_type", "RSA");
            paramMap.put("version", "3.0");

            if (extraBase != null) {
                paramMap.putAll(extraBase);
            }

            paramMap.put("biz_content", JSON.toJSONString(reqData));
            String encryptOriginData = SignUtils.getSignContent((JSONObject) JSON.toJSON(paramMap));
            log.debug("加签源数据==============>"+ encryptOriginData);
            paramMap.put("sign", RSAUtils.sign(ysConfig.getPriKeyV2(), encryptOriginData));

            if (fileMap != null) {
                paramMap.putAll(fileMap);
            }

            HttpHeaders headers = new HttpHeaders();
            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.debug("业务参数==============>" + JSONObject.toJSONString(reqData));
            HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(MapUtils.map2MultiValueMap(paramMap), headers);
            String result = restTemplate.postForObject(url, entity, String.class);

            log.debug("请求结果：{}", result);

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

    /**
     * 只用于新的进件接口
     *
     * @param url       请求链接
     * @param method    请求方法
     * @param reqData   请求参数
     * @param extraBase 额外的基本参数
     * @return
     */
    public JSONObject req(String url, String method, JSONObject reqData, Map<String, Object> extraBase) {
        return req(url, method, reqData, extraBase, null);
    }
}
