package com.cweb.controller.pay;

import com.alibaba.fastjson.JSONObject;
import com.cweb.config.SysConst;
import com.cweb.config.WxMsgConfig;
import com.hai.common.exception.ErrorCode;
import com.hai.common.exception.ErrorHelp;
import com.hai.common.exception.SysCode;
import com.hai.common.pay.WechatPayUtil;
import com.hai.common.pay.entity.WechatCallBackInfo;
import com.hai.common.pay.util.IOUtil;
import com.hai.common.pay.util.XmlUtil;
import com.hai.common.pay.util.sdk.WXPayConstants;
import com.hai.common.utils.HttpsUtils;
import com.hai.common.utils.ResponseMsgUtil;
import com.hai.common.utils.WxUtils;
import com.hai.entity.*;
import com.hai.enum_type.GoodsType;
import com.hai.enum_type.PayType;
import com.hai.model.ResponseData;
import com.hai.model.WxSharingOrderRequestModel;
import com.hai.model.WxSharingReceiversVO;
import com.hai.service.HighOrderService;
import com.hai.service.HighProfitSharingRecordService;
import com.hai.service.HighUserService;
import com.hai.service.TelApiService;
import com.hai.service.pay.NotifyService;
import com.hai.service.pay.PayRecordService;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.sf.cglib.beans.BeanMap;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.*;
import java.util.*;

@Controller
@RequestMapping(value = "/wechatpay")
@Api(value = "微信支付")
public class WechatPayController {

    private static Logger log = LoggerFactory.getLogger(WechatPayController.class);

    private WXPayConstants.SignType signType;

    @Resource
    private NotifyService notifyService;
    @Resource
    private PayRecordService payRecordService;
    @Resource
    private WechatPayUtil wechatPayUtil;

    @Resource
    private HighOrderService highOrderService;

    @Resource
    private HighUserService highUserService;

    @Resource
    private TelApiService telApiService;
    @Resource
    private HighProfitSharingRecordService highProfitSharingRecordService;

    @RequestMapping(value = "/notify", method = RequestMethod.POST)
    @ApiOperation(value = "微信支付 -> 异步回调")
    public void wechatNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            log.info("微信支付 -> 异步通知：处理开始");

            String resXml = "";    // 反馈给微信服务器
            String notifyXml = null;    // 微信支付系统发送的数据（<![CDATA[product_001]]>格式）
            notifyXml = IOUtil.inputStreamToString(request.getInputStream(), "UTF-8");

            log.info("微信支付系统发送的数据：" + notifyXml);
            SortedMap<String, String> map = XmlUtil.parseXmlToTreeMap(notifyXml, "UTF-8");

            resXml = notifyService.wechatNotify(map);

/*            if (SignatureUtil.reCheckIsSignValidFromWeiXin(notifyXml, SysConst.getSysConfig().getWxApiKey(), "UTF-8")) {
                log.info("微信支付系统发送的数据：" + notifyXml);
                SortedMap<String, String> map = XmlUtil.parseXmlToTreeMap(notifyXml, "UTF-8");

                resXml = notifyService.wechatNotify(map);
            } else {
                log.error("微信支付 -> 异步通知：验签失败");
                log.error("apiKey：" + SysConst.getSysConfig().getWxApiKey());
                log.error("返回信息：" + notifyXml);
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[签名验证错误]]></return_msg>" + "</xml> ";
            }*/

            new Thread(() -> {
                // 查询订单信息
                HighOrder order = highOrderService.getOrderByOrderNo(map.get("out_trade_no"));
                if (order == null) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.NOT_FOUND_ORDER, "");
                }
                HighUser highUser = highUserService.findByUserId(order.getMemId());
                HighChildOrder presentation = highOrderService.getChildOrderByPresentation(order.getId());
                WxMsgConfig.pushOneUser(
                        presentation.getGoodsName() + "(" + GoodsType.getNameByType(presentation.getGoodsType()) + ")",
                        String.valueOf(order.getPayPrice()),
                        order.getOrderNo(),
                        order.getPayTime(),
                        PayType.getNameByType(order.getPayType()), order.getId(),
                        highUser.getOpenId());
            }).start();

            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
            log.info("微信支付 -> 异步通知：处理完成");
        } catch (Exception e) {
            log.error("WechatPayController --> wechatNotify() error!", e);
        }
    }

    @RequestMapping(value = "/addLedgerReceiver", method = RequestMethod.POST)
    @ApiOperation(value = "微信支付 -> 添加分账接收方")
    public void addLedgerReceiver(@RequestParam(name = "sub_mch_id", required = true) String sub_mch_id,
                                   HttpServletRequest request, HttpServletResponse response) {
        try {

            WxSharingReceiversVO receiversVO = new WxSharingReceiversVO();
            receiversVO.setAccount("1603942866");
            receiversVO.setType("MERCHANT_ID");
            receiversVO.setName("重庆惠昕石化有限责任公司");
            receiversVO.setRelation_type("SERVICE_PROVIDER");

            Map<String , String> map = new HashMap<>();

            map.put("mch_id" , "1289663601");
            map.put("sub_mch_id" , sub_mch_id);
            map.put("appid" , "wxa075e8509802f826");
            map.put("nonce_str" , WxUtils.makeNonStr());
            map.put("sign_type" , "HMAC-SHA256");
            map.put("receiver" , JSONObject.toJSONString(receiversVO));

            String sign = WxUtils.generateSignature(map, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);

            map.put("sign" , sign);

            String url = "https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver";
            String xm = WxUtils.mapToXml(map);
            String rest = String.valueOf(HttpsUtils.postData(url, xm));

            System.out.println(rest);
            log.info("微信支付 -> 添加分账接收方：处理开始");
        } catch (Exception e) {
            log.error("WechatPayController --> wechatNotify() error!", e);
        }
    }


    String getToken(String method, String url, String body) throws UnsupportedEncodingException, SignatureException, NoSuchAlgorithmException, InvalidKeyException, FileNotFoundException {

        long timeMillis = System.currentTimeMillis();
        String nonceStr = String.valueOf(timeMillis);
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        PrivateKey privateKey = PemUtil.loadPrivateKey(new FileInputStream("G:/hurui-project/hai-parent/hai-cweb/src/main/resources/privatekey/apiclient_key.pem"));
        String signature = sign(privateKey,message.getBytes("utf-8"));

        return "mchid=\"" + SysConst.getSysConfig().getWxSubMchId() + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + "1B08DC2A078B0B1F77A65C97C445AAD545B5EAA6" + "\","
                + "signature=\"" + signature + "\"";
    }

    String sign(PrivateKey privateKey,byte[] message) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privateKey);
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    String buildMessage(String method, String url, long timestamp, String nonceStr, String body) {
        return method + ""
                + url + ""
                + timestamp + ""
                + nonceStr + ""
                + body + "";
    }

}
