package com.younike.hlpay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.younike.common.utils.StringUtils;
import com.younike.hlpay.constant.AppPayType;
import com.younike.hlpay.constant.BizType;
import com.younike.hlpay.constant.HeliPayContants;
import com.younike.hlpay.constant.PayType;
import com.younike.hlpay.dto.*;
import com.younike.hlpay.service.IPayService;
import com.younike.hlpay.util.BeanUtils;
import com.younike.hlpay.util.Disguiser;
import com.younike.hlpay.util.HttpClientService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.httpclient.HttpStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static com.younike.hlpay.constant.HeliPayContants.*;

/**
 * @author chenpengfei
 */
@Service
@Log4j2
public class PayServiceImpl implements IPayService {

    @Value("${hlb.wechat.xcx.cbUrl}")
    private String hlbCbUrl;

    @Value("${hlb.wechat.xcx.appid}")
    private String hlbAppId;

    @Value("${hlb.refund.cbUrl}")
    private String refundCbUrl;


    @Override
    public Map<String, Object> wxAppletPay(PaymentParam paymentParam, BillInfo billInfo) {
        // 微信小程序支付对象
        AppPayPublicCreateOrderVo payVo = new AppPayPublicCreateOrderVo();
        payVo.setP1_bizType("AppPayApplet");
        payVo.setP2_orderId(HLB_PAY_PREFIX_WX + paymentParam.getOrderId());
        String customerNumber = MAIN_CUSTOMER_NUMBER;
        // 订单支付，分账
        payVo.setSplitBillType("FIXED_AMOUNT");
        // 分账规则串
        payVo.setRuleJson(billInfo.getSplitBillRule());

        // 营销补贴
        if (StringUtils.isNotEmpty(billInfo.getMarketingRuleStr())) {
            payVo.setP23MarketingRule(billInfo.getMarketingRuleStr());
        }
        payVo.setP12_notifyUrl(hlbCbUrl);
        payVo.setP3_customerNumber(customerNumber);
        payVo.setP4_payType(PayType.APPLET.name());
        payVo.setP5_appid(hlbAppId);
        payVo.setP6_deviceInfo("DEVICE");
        payVo.setP7_isRaw("1");
        payVo.setP8_openid(billInfo.getOpenId());
        payVo.setP9_orderAmount(billInfo.getOrderAmount().toString());
        payVo.setP10_currency("CNY");
        payVo.setP11_appType(AppPayType.WXPAY.name());
        payVo.setP14_orderIp("127.0.0.1");
        payVo.setP15_goodsName("优鲜信");
        Map<String, String> map = null;
        try {
            map = BeanUtils.convertBean(payVo, new LinkedHashMap());
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        String oriMessage = BeanUtils.getSignedByPresetParameter(map, AppPayPublicCreateOrderVo.NEED_SIGN_PARAMS);
        log.info("签名原文串：" + oriMessage);
        String sign = Disguiser.disguiseMD5(oriMessage.trim());
        log.info("签名串：" + sign);
        map.put("sign", sign);
        log.info("发送参数：" + map);
        Map<String, Object> resultMap = HttpClientService.getHttpResp(map, HeliPayContants.PAY_REQUEST_URL);
        return resultMap;
    }

    @Override
    public Map<String, Object> aliSdkPay(PaymentParam paymentParam, BillInfo billInfo) {
        // 微信小程序支付对象
        SDKCreateOrderVo payVo = new SDKCreateOrderVo();
        payVo.setP1_bizType("AppPay");
        String customerNumber = MAIN_CUSTOMER_NUMBER;
        // 判断业务类型
        // 订单支付，分账
        payVo.setSplitBillType("FIXED_AMOUNT");
        // 分账规则串
        payVo.setRuleJson(billInfo.getSplitBillRule());

        // 营销补贴
        if (StringUtils.isNotEmpty(billInfo.getMarketingRuleStr())) {
            payVo.setP18MarketingRule(billInfo.getMarketingRuleStr());
        }
        payVo.setP9_notifyUrl(hlbCbUrl);
        payVo.setP12_goodsName("家政服务订单");
        payVo.setP2_orderId(HLB_PAY_PREFIX_ALI + paymentParam.getOrderId());
        payVo.setP3_customerNumber(customerNumber);
        payVo.setP4_payType("SCAN");
//        if (billInfo.getMarketingAmount() != null) {
//            payVo.setP5_orderAmount(billInfo.getOrderAmount().add(billInfo.getMarketingAmount()).toString());
//        } else {
//            payVo.setP5_orderAmount(billInfo.getOrderAmount().toString());
//        }
        payVo.setP5_orderAmount(billInfo.getOrderAmount().toString());
        payVo.setP6_currency("CNY");
        payVo.setP7_authcode("1");
        payVo.setP8_appType("ALIPAY");
        payVo.setP11_orderIp("127.0.0.1");
//        payVo.setP10_successToUrl("ALIPAY");
        payVo.setP13_goodsDetail("家政服务订单");
        payVo.setP14_desc("用户付款");
        Map<String, String> map = null;
        try {
            map = BeanUtils.convertBean(payVo, new LinkedHashMap());
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        String oriMessage = BeanUtils.getSignedByPresetParameter(map, SDKCreateOrderVo.NEED_SIGN_PARAMS);
        log.info("签名原文串：" + oriMessage);
        String sign = Disguiser.disguiseMD5(oriMessage.trim());
        log.info("签名串：" + sign);
        map.put("sign", sign);
        log.info("发送参数：" + map);
        Map<String, Object> resultMap = HttpClientService.getHttpResp(map, HeliPayContants.PAY_REQUEST_URL);
        return resultMap;
    }

    /**
     * 支付宝SDK预支付
     *
     * @param param  支付参数
     * @param openId 微信openId，仅仅微信支付使用，其他传Null
     * @return
     */
    @Override
    public Map<String, Object> hlbPay(PaymentParam param, String openId) {
        BillInfo billInfo = new BillInfo();
        // 判断业务类型(是否是 0商家  1是个人)
        if (param.getMerchantType().equals(1)) {

            billInfo.setOrderAmount(param.getTotalAmount());
            if (StringUtils.isEmpty(openId)) {
                // 支付宝SDK支付
                return aliSdkPay(param, billInfo);
            } else {
                // 微信小程序支付
                billInfo.setOpenId(openId);
                return wxAppletPay(param, billInfo);
            }
        } else {
            billInfo.setOrderAmount(param.getTotalAmount());
            //商家类型为商家的

            //商家可得金额
            BigDecimal splitAmount = param.getShopAmount();
            //总营销金额
            BigDecimal marketingAmount = param.getTotalAmount();
            //商家邮箱
            String email = param.getEmail();

            //分账信息
            List<SplitBillInfo> splitBillInfos = new ArrayList<>();
            SplitBillInfo splitBillInfo = SplitBillInfo.builder()
                    .splitBillMerchantEmail(email).splitBillAmount(splitAmount).build();
            splitBillInfos.add(splitBillInfo);
            billInfo.setSplitBillRule(JSON.toJSONString(splitBillInfos));
            log.info("合利宝预支付 -- 分账规则字符串：" + billInfo.getSplitBillRule());
            if (marketingAmount.compareTo(BigDecimal.ZERO) > 0) {
                billInfo.setMarketingAmount(marketingAmount);
                log.info("合利宝预支付 -- 营销规则字符串：" + billInfo.getMarketingRuleStr());
            }

            // 是否使用平台优惠券（营销补贴）
              // 总营销金额
            if (StringUtils.isEmpty(openId)) {
                // 支付宝SDK支付
                return aliSdkPay(param, billInfo);
            } else {
                // 微信小程序支付
                billInfo.setOpenId(openId);
                return wxAppletPay(param, billInfo);
            }
        }
    }

    /**
     * 全额退款
     * 三方配送且骑手已接单，会扣除运费
     *
     * @param orderId 订单ID
     * @return 成功与否
     */
    @Override
    public boolean orderRefund(String orderId, String merchantEmail, BigDecimal amount, BigDecimal shopAmount, String payWay){
        AppPayRefundOrderVo vo = new AppPayRefundOrderVo();
        vo.setP1_bizType("AppPayRefund");
        if ("001".equals(payWay)) {
            vo.setP2_orderId(HLB_PAY_PREFIX_WX + orderId);
        } else {
            vo.setP2_orderId(HLB_PAY_PREFIX_ALI + orderId);
        }
        vo.setP3_customerNumber(MAIN_CUSTOMER_NUMBER);
        vo.setP4_refundOrderId(orderId + System.currentTimeMillis());
        vo.setP5_amount(amount.toString());
        vo.setP6_callbackUrl(refundCbUrl);
        vo.setP7_desc("用户全额退款");
        List<RefundSplitBillInfo> refundSplitBillInfos = new ArrayList<>();
        RefundSplitBillInfo mainSplitBillInfo = RefundSplitBillInfo.builder()
                .splitBillMerchantEmail(MAIN_CUSTOMER_MAIL).refundAmount(amount.subtract(shopAmount)).build();
        refundSplitBillInfos.add(mainSplitBillInfo);
        RefundSplitBillInfo splitBillInfo = RefundSplitBillInfo.builder()
                .splitBillMerchantEmail(merchantEmail).refundAmount(shopAmount).build();
        refundSplitBillInfos.add(splitBillInfo);
        String rule = JSON.toJSONString(refundSplitBillInfos);
        log.info("退款分账规则字符串：" + rule);
        vo.setRuleJson(rule);
        return refund(vo);
    }

    /**
     * 合利宝退款服务
     */
    private boolean refund(AppPayRefundOrderVo vo){
        try {
            Map<String, String> map = BeanUtils.convertBean(vo, new LinkedHashMap());
            String oriMessage = BeanUtils.getSignedByPresetParameter(map, AppPayRefundOrderVo.NEED_SIGN_PARAMS);
            log.info("签名原文串：" + oriMessage);
            String sign = Disguiser.disguiseMD5(oriMessage.trim());
            log.info("签名串：" + sign);
            map.put("sign", sign);
            log.info("发送参数：" + map);
            Map<String, Object> resultMap = HttpClientService.getHttpResp(map, HeliPayContants.PAY_REQUEST_URL);
            log.info("响应结果：" + resultMap);
            if ((Integer) resultMap.get("statusCode") == HttpStatus.SC_OK) {
                String resultMsg = (String) resultMap.get("response");
                AppPayRefundOrderResponseVo orderResponseVo = JSONObject.parseObject(resultMsg, AppPayRefundOrderResponseVo.class);
                log.info(JSON.toJSONString(orderResponseVo));
                String assemblyRespOriSign = BeanUtils.getSignedByPresetParameter(orderResponseVo, AppPayRefundOrderResponseVo.NEED_SIGN_PARAMS);
                log.info("组装返回结果签名串：" + assemblyRespOriSign);
                String responseSign = orderResponseVo.getSign();
                log.info("响应签名：" + responseSign);
                String checkSign = Disguiser.disguiseMD5(assemblyRespOriSign.trim());
                if (checkSign.equals(responseSign)) {
                    if ("0001".equals(orderResponseVo.getRt2_retCode())) {
                        // 退款申请成功
                        log.info("退款申请成功 " + orderResponseVo.getRt5_orderId());
                        return true;
                    } else {
                        // TODO 退款失败，将请求存在记录表中

                        throw new RuntimeException("订单退款失败 -- " + orderResponseVo.getRt3_retMsg());
                    }
                } else {
                    // TODO 退款失败，将请求存在记录表中

                    throw new RuntimeException("退款申请失败：" + orderResponseVo.getRt3_retMsg());
                }
            } else {
                // TODO 退款失败，将请求存在Redis中，待处理
//                recordMsg(vo.getP2_orderId().split("-")[1], oriMessage, JSON.toJSONString(resultMap));
                throw new RuntimeException("退款申请失败：" + resultMap.get("statusCode"));
            }
        } catch (Exception e) {
            // TODO 退款失败，将请求存在Redis中，待处理
//            recordMsg(vo.getP2_orderId().split("-")[1], JSON.toJSONString(vo), "");
            throw new RuntimeException("退款申请失败：" + e.getMessage());
        }
    }
}
