package com.web.rocketmq.consumer;

import com.alibaba.fastjson.JSONObject;
import com.hai.common.exception.ErrorCode;
import com.hai.common.exception.ErrorHelp;
import com.hai.common.exception.SysCode;
import com.hai.common.pay.util.XmlUtil;
import com.hai.common.pay.util.sdk.WXPayConstants;
import com.hai.common.utils.WxUtils;
import com.hai.entity.*;
import com.hai.enum_type.GasChannel;
import com.hai.enum_type.GasChannelPayPlatformType;
import com.hai.enum_type.MerchantStoreSourceType;
import com.hai.model.HighMerchantStoreModel;
import com.hai.model.ResultProfitSharing;
import com.hai.order.service.OrderService;
import com.hai.order.type.OrderChildGoodsType;
import com.hai.order.type.OrderPayType;
import com.hai.order.type.OrderProductType;
import com.hai.order.type.OrderStatus;
import com.hai.service.HighGasChannelConfigService;
import com.hai.service.HighMerchantStoreService;
import com.hai.service.HighProfitSharingRecordService;
import lombok.extern.slf4j.Slf4j;
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.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.security.KeyStore;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
@RocketMQMessageListener(consumerGroup = "order-profit-sharing-group", topic = "order-topic",selectorExpression = "profit-sharing")
public class OrderProfitSharingConsumer implements RocketMQListener<HighOrder> {

    @Resource
    private OrderService orderService;

    @Resource
    private HighProfitSharingRecordService profitSharingRecordService;

    @Resource
    private HighMerchantStoreService merchantStoreService;

    @Resource
    private HighGasChannelConfigService gasChannelConfigService;

    @Override
    public void onMessage(HighOrder order) {
        String resultXml = null;
        if (order.getPayType().equals(OrderPayType.PAY_TYPE2.getNumber())) {
            List<HighChildOrder> orderList = order.getHighChildOrderList().stream()
                    .filter(o -> o.getGoodsType().equals(OrderChildGoodsType.TYPE3.getNumber())).collect(Collectors.toList());

            if (order.getProductType().equals(OrderProductType.PRODUCT_TYPE6.getNumber())) {
                HighMerchantStore store = merchantStoreService.getDetailById(orderList.get(0).getGoodsId());
                HighGasChannelConfig gasChannelConfig;
                if (store.getSourceType().equals(MerchantStoreSourceType.type1.getNumber())) {
                    gasChannelConfig = gasChannelConfigService.getConfig(GasChannel.type1, GasChannelPayPlatformType.type1);

                } else if (store.getSourceType().equals(MerchantStoreSourceType.type2.getNumber())) {
                    gasChannelConfig = gasChannelConfigService.getConfig(GasChannel.type2, GasChannelPayPlatformType.type1);

                } else if (store.getSourceType().equals(MerchantStoreSourceType.type3.getNumber())) {
                    gasChannelConfig = gasChannelConfigService.getConfig(GasChannel.type3, GasChannelPayPlatformType.type1);

                } else if (store.getSourceType().equals(MerchantStoreSourceType.type4.getNumber())) {
                    gasChannelConfig = gasChannelConfigService.getConfig(GasChannel.type4, GasChannelPayPlatformType.type1);

                } else {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未配置分账参数");
                }

                BigDecimal rake = new BigDecimal("0.01");
                // 计算微信收取的手续费     支付金额 * 0.002      注：如果与两个相邻数字的距离相等，则为上舍入的舍入模式。
                BigDecimal wxHandlingFee = order.getPayRealPrice().multiply(new BigDecimal("0.002")).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                BigDecimal price = order.getPayRealPrice().subtract(wxHandlingFee);
                // 计算分账金额    手续费后的价格 * 0.01  注：如果与两个相邻数字的距离相等，则为上舍入的舍入模式。
                BigDecimal profitSharingAmount = price.multiply(rake).setScale(2, BigDecimal.ROUND_DOWN);

                resultXml = this.wechatSharingRecord(
                        order.getExt1(),
                        order.getAccountMerchantNum(),
                        gasChannelConfig.getProfitSharingReceiversNo(),
                        gasChannelConfig.getProfitSharingReceiversName(),
                        order.getPaySerialNo(),
                        order.getOrderNo(),
                        profitSharingAmount);
                ResultProfitSharing resultProfitSharing = XmlUtil.getObjectFromXML(resultXml, ResultProfitSharing.class);
                HighProfitSharingRecord sharingRecord = new HighProfitSharingRecord();
                sharingRecord.setOutOrderNo(order.getOrderNo());
                sharingRecord.setTransactionId(order.getPaySerialNo());
                sharingRecord.setOrderId(order.getId().toString());
                sharingRecord.setStatus(resultProfitSharing.getResult_code());
                sharingRecord.setPrice(profitSharingAmount);
                sharingRecord.setCreateTime(new Date());
                sharingRecord.setContent(resultXml);
                profitSharingRecordService.insert(sharingRecord);

            } else {
                BigDecimal rake = new BigDecimal("0.01");
                // 计算微信收取的手续费     支付金额 * 0.002      注：如果与两个相邻数字的距离相等，则为上舍入的舍入模式。
                BigDecimal wxHandlingFee = order.getPayRealPrice().multiply(new BigDecimal("0.002")).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                BigDecimal price = order.getPayRealPrice().subtract(wxHandlingFee);
                // 计算分账金额    手续费后的价格 * 0.01  注：如果与两个相邻数字的距离相等，则为上舍入的舍入模式。
                BigDecimal profitSharingAmount = price.multiply(rake).setScale(2, BigDecimal.ROUND_DOWN);

                resultXml = this.wechatSharingRecord(
                        order.getExt1(),
                        order.getAccountMerchantNum(),
                        "1603942866",
                        "惠昕石化",
                        order.getPaySerialNo(),
                        order.getOrderNo(),
                        profitSharingAmount);
                ResultProfitSharing resultProfitSharing = XmlUtil.getObjectFromXML(resultXml, ResultProfitSharing.class);
                HighProfitSharingRecord sharingRecord = new HighProfitSharingRecord();
                sharingRecord.setOutOrderNo(order.getOrderNo());
                sharingRecord.setTransactionId(order.getPaySerialNo());
                sharingRecord.setOrderId(order.getId().toString());
                sharingRecord.setStatus(resultProfitSharing.getResult_code());
                sharingRecord.setPrice(profitSharingAmount);
                sharingRecord.setCreateTime(new Date());
                sharingRecord.setContent(resultXml);
                profitSharingRecordService.insert(sharingRecord);
            }
        }
    }

    /**
     * 【微信】分账
     * @param appid
     * @param subMchId
     * @param receiversAccount      接收者商户号
     * @param receiversAccountName  接收者商户名称
     * @param transaction_id        第三方交易订单号
     * @param out_order_no          交易订单号
     * @param amount                分账金额
     */
    public String wechatSharingRecord(String appid, String subMchId, String receiversAccount, String receiversAccountName,String transaction_id,String out_order_no, BigDecimal amount) {
        try {
            Map<String,String> param = new LinkedHashMap<>();
            param.put("appid", appid);
            param.put("mch_id", "1289663601");
            param.put("sub_mch_id" , subMchId);
            param.put("transaction_id" , transaction_id);
            param.put("out_order_no" , out_order_no);
            param.put("nonce_str" , WxUtils.makeNonStr());

            List<Map<String,Object>> receiversList = new ArrayList<>();
            Map<String,Object> receiversMap = new LinkedHashMap<>();
            receiversMap.put("type", "MERCHANT_ID");
            receiversMap.put("account", receiversAccount);
            receiversMap.put("amount", amount.multiply(new BigDecimal("100")).intValue());
            receiversMap.put("description", "分给商户：" + receiversAccountName);
            receiversList.add(receiversMap);
            param.put("receivers" , JSONObject.toJSONString(receiversList));
            String signStr = WxUtils.generateSignature(param, "Skufk5oi85wDFGl888i6wsRSTkdd5df5" , WXPayConstants.SignType.HMACSHA256);
            param.put("sign" , signStr);

            // 请求分账返回的结果
            return this.wechatRequest(param.get("mch_id"), WxUtils.mapToXml(param));


        } catch (Exception e) {
            log.error("CmsContentController --> getCorporateAdvertising() error!", e);
        }
        return null;
    }

    /**
     * 【微信】分账请求
     * @param mchId
     * @param data
     * @return
     * @throws Exception
     */
    public String wechatRequest(String mchId, String data) throws Exception {
        /**
         * 注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的
         */
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        //P12文件目录 证书路径，这里需要你自己修改，linux下还是windows下的根路径
        FileInputStream instream = new FileInputStream("/home/project/wx_cert/1289663601_apiclient_cert.p12");
        try {
            keyStore.load(instream, "1289663601".toCharArray());//这里写密码..默认是你的MCHID
        } finally {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, "1289663601".toCharArray()).build();//这里也是写密码的
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        //小程序退款需要调用双向证书的认证
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        try {
            HttpPost httpost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/profitsharing"); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "text/xml");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpClient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } catch (Exception e){
            throw new RuntimeException(e);
        } finally {
            httpClient.close();
        }
    }
}
