package com.tzy.framework.pay.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.huifu.adapay.Adapay;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.model.MerConfig;
import com.huifu.adapay.model.Payment;
import com.huifu.adapay.model.PaymentReverse;
import com.huifu.adapay.model.Refund;
import com.tzy.common.utils.*;
import com.tzy.framework.pay.config.HfPayConfig;
import com.tzy.framework.pay.dto.*;
import com.tzy.framework.pay.service.HfPayService;
import com.tzy.framework.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class HfPayServiceImpl implements HfPayService {

    @Autowired
    private HfPayConfig hfPayConfig;;

    private static String appid = "app_db57e4cc-6324-430a-9ffc-dd836f412cb9";

    public static String regSpecial = "[`~!@$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）_+|{}‘；：”“’。，、？]";

    /**
     * 预加载 注册宝付配置
     */
    @PostConstruct
    public void init() throws Exception {
        if (null == hfPayConfig) hfPayConfig = new HfPayConfig();
        /**
         * debug 模式，开启后有详细的日志
         */
        Adapay.debug = hfPayConfig.isDebug();
//        Adapay.debug = false;
        /**
         * prodMode 模式，默认为生产模式，false可以使用mock模式
         */
        Adapay.prodMode = hfPayConfig.isProdMode();
        log.info("  prodMode 模式 {} ",Adapay.prodMode);
//        Adapay.prodMode = true;
        /**
         * 初始化商户配置，服务器启动前，必须通过该方式初始化商户配置完成
         * apiKey为prod模式的API KEY
         * mockApiKey为mock模式的API KEY
         * rsaPrivateKey为商户发起请求时，用于请求参数加签所需要的RSA私钥
         */
        String apiKey = "api_live_62f4a9d5-905e-4d64-85f0-136a9c0620a5";
        String mockApiKey = "api_test_29708ffc-1d3f-4b24-8e7b-60073b138b9e";
        String rsaPrivateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIl2NugFoWa+HUk/xQyUx69u85pC7vbtZbtOWjD3Yqt6PnE7mT6B4GOf7lDYd4NrggzPaJ067yo8xv8GCNla+flP7KbRhbrp6h+U4L3NX32PQSvZJWjnGxUkOm+tDp3PfBPl48pf8/X7oocafn0ZGqZslNZh8/BTVJhwOi52G8i3AgMBAAECgYBPXbi/6BhTaOsh0rbj17cffHEcHQ859MFrDwcWBI+ssC0DVcTaCUTUYI/Jj+IZN+ZjnREqzs8t1N+UeRh83oE676Gl/+dQVgeQ7muugoCZ0FI7kEKsFQILSSXq0wAC7kfZJv3fVs3p9WEyjd9e90nWqO45vszAuCAijnIRV8vGeQJBALyvvgJGAGfMCqqFZdMdk9C+SEf8rjtuTezQzHOAw+kIYvyZZvmCeJRbYbZ7myoa6QaVquy52MSR2IDZyqPsQhUCQQC6gD++Gl/jhWsWejAl1VaMLq+sGQYtAp+rt5OQMAHebDnMgovoTjWXpLocDA0IPFNGuHjvsxN43J3OUOe1cC6bAkBN9D2IKuuX9pChiqNa6WlcYID0XMyO+S9wm4McZSKLcE+VFLuacfDnOinQfpjIeH21nrgTPWT1MVxFP7Wcq8tRAkEApIDhOL6s29RgK/hlJcnyyD2Z6LQ99U++JUoM1/7wdw+BP/najHMH5JWBL6IVkLEdR2EKE2wifdYjP8uvRiQIhwJABYPLM4gq099OjkyA9U0zm8bbKqFDQYdrRhmDUjUiojFw9QHlck7BcBc01PmUjg7TN5uBTWyTTJY7pOWtS7s6Ag==";
        MerConfig merConfig = new MerConfig();
//        merConfig.setApiKey(apiKey);
//        merConfig.setApiMockKey(mockApiKey);
//        merConfig.setRSAPrivateKey(rsaPrivateKey);
        merConfig.setApiKey(hfPayConfig.getApiKey());
        merConfig.setApiMockKey(hfPayConfig.getApiMockKey());
        merConfig.setRSAPrivateKey(hfPayConfig.getRSAPrivateKey());
        Adapay.initWithMerConfig(merConfig);
    }

    /**
     * 执行一个支付交易
     *
     * @return 创建的支付对象
     * @throws Exception 异常
     */
    @Override
    public ResultMap tradeCreate(PaymentRequestDto paymentRequestDto) {
        ResultMap resultMap = new ResultMap();
        try {
            RechargeUserInfoDto rechargeUserInfoDto = paymentRequestDto.getRechargeUserInfoDto();
            System.out.println("=======execute payment begin=======");
            //创建支付对象的参数，全部参数请参考 https://docs.adapay.tech/api/index.html
            Map<String, Object> paymentParams = new HashMap<>(10);
            paymentParams.put("app_id", hfPayConfig.getAppid());
//            paymentParams.put("app_id", appid);
            String expireTime = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,paymentRequestDto.getExpireTime());
            paymentParams.put("time_expire", expireTime);
            paymentParams.put("order_no", paymentRequestDto.getOrderNo());
            paymentParams.put("pay_channel", paymentRequestDto.getPayWay());
            paymentParams.put("pay_amt", paymentRequestDto.getTotalAmount().toString());
            paymentParams.put("notify_url", hfPayConfig.getNotify_url());
            String msg = String.valueOf(paymentRequestDto.getBody());
            msg = Base64Util.subStringByBytes(msg,20).replaceAll(regSpecial," ");
            paymentParams.put("goods_title",msg );
            paymentParams.put("goods_desc", msg);
            Map device_info = new HashMap();
            device_info.put("device_ip", IpUtils.getIpAddr(ServletUtils.getRequest()));
//            device_info.put("device_ip", "116.232.75.101");
            paymentParams.put("device_info", device_info);

            //填写用户的实名认证信息
            if(null != rechargeUserInfoDto && rechargeUserInfoDto.isCheckUserAuth()){
                paymentParams.put("name",rechargeUserInfoDto.getUserName());//实名认证姓名
                paymentParams.put("certType","IDENTITY_CARD");//实名认证证件类型
                paymentParams.put("certNo",rechargeUserInfoDto.getCertificateNo());//实名认证证件号
                paymentParams.put("fixBuyer","T");//是否需要实名认证
            }
            //调用sdk方法，创建支付，得到支付对象
            log.info("汇付支付交易，请求参数：{}" , JSONObject.toJSONString(paymentParams));
            Map<String, Object> payment = Payment.create(paymentParams);
            JSONObject jsonResult = (JSONObject) payment;
            log.info("汇付支付交易，返回结果：{}" , jsonResult);
            if(null != jsonResult && !jsonResult.isEmpty() ) {
                String status = jsonResult.getString("status");
                if(!"succeeded".equals(status)){
                    return ResultMap.error(jsonResult.getString("error_msg"));
                }
                String paymentId = (String) jsonResult.get("id");
                JSONObject expend = (JSONObject) jsonResult.get("expend");
                String pay_info = expend.getString("pay_info");
                if (StringUtils.isEmpty(pay_info)) pay_info = expend.getString("qrcode_url");
                Map<String, String> data = new HashMap<>();
                data.put("url", pay_info);
                resultMap.put("data", data);
                resultMap.put("merOrderId", paymentId);
                resultMap.put("orderNo", paymentRequestDto.getOrderNo());
                return resultMap;
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return ResultMap.error("下单失败");
    }

    /**
     * 查询
     * @param appid
     * @throws Exception
     */
    @Override
    public PaymentInfoResponseDto queryOrder(String appid, String payWay, String  id) {
        PaymentInfoResponseDto paymentInfoResponseDto = new PaymentInfoResponseDto();
        String errMsg = "";
        try {
            System.out.println("=======query payment begin=======");
            System.out.println("支付查询请求参数：" + JSONObject.toJSONString(id));
            Map<String, Object> payment = Payment.query(id);
            System.out.println("支付查询返回参数：" + JSONObject.toJSONString(payment));
            System.out.println("=======query payment end=======");
            JSONObject jsonResult = (JSONObject) payment;
            log.info("汇付支付交易，返回结果：{}" , jsonResult);
            if(null != jsonResult && !jsonResult.isEmpty() ) {
                String status = jsonResult.getString("status");
                if("succeeded".equals(status)){
                    paymentInfoResponseDto = PaymentInfoResponseDto.ok();
                    paymentInfoResponseDto.setOrderNo(id);
                    paymentInfoResponseDto.setPayWay(payWay);
                    paymentInfoResponseDto.setPaymentNo(id);
                    String orderAmt = StringUtils.isNotEmpty((String) payment.get("pay_amt")) ? (String) payment.get("pay_amt") : "0";
                    paymentInfoResponseDto.setPaymentPrice(new BigDecimal(orderAmt));
                    paymentInfoResponseDto.setActualPayment(new BigDecimal(orderAmt));
                    Date finishedDate = new Date();
                    paymentInfoResponseDto.setPaymentSuccessTime(finishedDate);
                    paymentInfoResponseDto.setSuccess(true);
                    return paymentInfoResponseDto;
                }
                return paymentInfoResponseDto.error(-1,jsonResult.getString("error_msg"));
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
            errMsg = "下单失败";
        }
        return PaymentInfoResponseDto.error(-2,errMsg);
    }

    /**
     * 撤销交易
     * @param paymentRequestDto
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> reverse(PaymentRequestDto paymentRequestDto)  {
        System.out.println("=======create Reverse  begin=======");
        Map<String, Object> reverse = new HashMap<>();
        try {
            reverse.put("payment_id", paymentRequestDto.getMerOrderId());
            reverse.put("app_id", hfPayConfig.getAppid());
//            reverse.put("app_id", appid);
            reverse.put("order_no", paymentRequestDto.getOrderNo());
            reverse.put("notify_url", hfPayConfig.getNotify_url());
            reverse.put("reverse_amt", paymentRequestDto.getTotalAmount().toString());
            reverse.put("reason", paymentRequestDto.getMsg());
            reverse.put("expand", paymentRequestDto.getOrderNo());
            System.out.println("创建撤销对象" + JSONObject.toJSONString(reverse));
            reverse = PaymentReverse.create(reverse);
        } catch (BaseAdaPayException e) {
            e.printStackTrace();
        }
        System.out.println("创建撤销对象返回参数：" + JSONObject.toJSONString(reverse));
        System.out.println("=======create Reverse  end=======");
        return reverse;
    }
    /**
     * 查询撤销对象
     *
     * @param reverse_id 要查询的支付id
     * @return 查询的支付对象
     * @throws Exception 异常
     */
    @Override
    public Map<String, Object> queryReverse(String reverse_id) {
        System.out.println("=======query Reverse  begin=======");
        Map<String, Object> reverse = new HashMap<>();
        try {
            reverse.put("reverse_id", reverse_id);
            System.out.println("查询撤销对象请求参数：" + JSONObject.toJSONString(reverse));
            reverse = PaymentReverse.query(reverse);
        } catch (BaseAdaPayException e) {
            e.printStackTrace();
        }
        System.out.println("查询撤销对象返回参数：" + JSONObject.toJSONString(reverse));
        System.out.println("=======query Reverse  end=======");
        return reverse;
    }
    /**
     * 退款交易
     *
     * @param refundRequestDto 要退款
     * @return 创建的退款对象
     * @throws Exception 异常
     */
    @Override
    public ResultMap refund(RefundRequestDto refundRequestDto) {
        System.out.println("=======execute refund begin=======");
        String errMsg = "";
        ResultMap refund = new ResultMap();
        try {
            String refundOrderId = RandomUtil.getRandomOld(RandomUtil.REFUND_NO);
            Map<String, Object> refundParams = new HashMap<String, Object>(2);
            refundParams.put("refund_amt", refundRequestDto.getRefundAmount().setScale(2).toString());
            refundParams.put("app_id", refundRequestDto.getAppid());
            refundParams.put("refund_order_no", refundOrderId);
//            refundParams.put("refund_order_no", refundRequestDto.getRefundNo());
            refundParams.put("notify_url",hfPayConfig.getRefundNotifyUrl());
            System.out.println("退款请求参数：" + JSONObject.toJSONString(refundParams));
            JSONObject retJson = (JSONObject) Refund.create(refundRequestDto.getOrderNo(), refundParams);
            if(null != retJson && !retJson.isEmpty()) {
                //判断状态
                //判断交易状态
                Map<String, String> stringStringMap = new HashMap<>();
                if("succeeded".equals(retJson.getString("status")) ) {
                    stringStringMap.put("out_refund_no", refundOrderId);
                    stringStringMap.put("refund_id", String.valueOf(retJson.get("id")));
                    try{
                        stringStringMap.put("refund_fee", String.valueOf(Double.parseDouble(String.valueOf(retJson.get("refund_amt")))));
                    }catch (NumberFormatException e){
                        stringStringMap.put("refund_fee", String.valueOf(Double.parseDouble(String.valueOf(retJson.get("refund_amt")))));
                    }
                    stringStringMap.put("fund_change", "Y");
                    return  ResultMap.ok()
                            .put("data",stringStringMap)
                            ;
                }else if("pending".equals(retJson.getString("status")) ) {//交易处理中
                    stringStringMap.put("out_refund_no", refundOrderId);
                    stringStringMap.put("fund_change", "P");
                    return  ResultMap.ok()
                            .put("data",stringStringMap)
                            ;
                } else {
                    errMsg = retJson.getString("error_msg");
                }
            }else{
                errMsg = "退款请求失败！";
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("退款返回参数：" + JSONObject.toJSONString(refund));
        System.out.println("=======execute refund end=======");
        return ResultMap.error(-2,errMsg);
    }
    /**
     * 根据refundNo查询一个退款交易
     *
     * @param refundRequestDto 要查询退款的 refundNo
     * @return 查询的退款对象，可能含多个退款明细RefundDetail
     * @throws Exception 异常
     */
    @Override
    public ResultMap queryRefund( RefundRequestDto refundRequestDto)  {
        String errMsg = "";
        System.out.println("=======query refund by paymentId begin=======");
        try {
            Map<String, Object> refundParams = new HashMap<String, Object>(1);
            if(StringUtils.isNotEmpty(refundRequestDto.getRefundNo())){
                refundParams.put("refund_order_no", refundRequestDto.getRefundNo());
            }else if(StringUtils.isNotEmpty(refundRequestDto.getMerOrderId())){
                refundParams.put("payment_id", refundRequestDto.getMerOrderId());
            }else if(StringUtils.isNotEmpty(refundRequestDto.getOrderNo())){
                refundParams.put("payment_id", refundRequestDto.getOrderNo());
            }
            log.info("通过refundNo查询退款交易，请求参数：{}" , JSONObject.toJSONString(refundParams));
            JSONObject retJson = (JSONObject) Refund.query(refundParams);
            log.info("通过refundNo查询退款交易，返回参数：{}" , retJson);
            if(null != retJson && !retJson.isEmpty()) {
                //判断状态
                if("succeeded".equals(retJson.getString("status"))){
                    //判断交易状态-退款状态
                    if(retJson.getString("status").contains("succeeded") ){
                        Map<String, String> stringStringMap = new HashMap<>();
                        JSONArray refunds = retJson.getJSONArray("refunds");
                        StringBuffer out_refund_no = new StringBuffer();
                        StringBuffer refundTargetOrderId = new StringBuffer();
                        final BigDecimal[] refundFree = {new BigDecimal(0)};
                        if(null != refunds && refunds.size() > 0){
                            refunds.forEach( obj->{
                                JSONObject objson = (JSONObject)obj;
                                String refund_amt = objson.getString("refund_amt");
                                refundFree[0] = refundFree[0].add(new BigDecimal(refund_amt));
                                out_refund_no.append(objson.getString("refund_order_no"));
                                refundTargetOrderId.append(objson.getString("refund_id"));
                            });
                        }
                        stringStringMap.put("out_refund_no", out_refund_no.toString());
                        stringStringMap.put("refund_id", refundTargetOrderId.toString());
                        stringStringMap.put("refund_fee", String.valueOf(refundFree[0]));
                        stringStringMap.put("fund_change", "Y");
                        return  ResultMap.ok()
                                .put("data",stringStringMap)
                                ;
                    }else{
                        errMsg = retJson.getString("error_msg");
                    }
                }else{
                    try{
                        errMsg = retJson.getString("error_msg");
                    }catch (Exception e){
                        errMsg = retJson.getString("error_code");
                    }
                }
            }else{
                errMsg = "退款查询请求失败！";
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("=======query refund by paymentId end=======");
        return ResultMap.error(-2,errMsg);
    }
    @Override
    public ResultMap close(PaymentRequestDto paymentRequestDto) {
        System.out.println("=======close payment begin=======");
        //关闭支付对象的参数，全部参数请参考 https://docs.adapay.tech/api/index.html
        //调用sdk方法，关闭支付，得到支付对象
        String errMsg = "";
        try {
            Map<String, Object> paymentParams = new HashMap<>(10);
            paymentParams.put("payment_id", paymentRequestDto.getOrderNo());
            paymentParams.put("reason", paymentRequestDto.getMsg());
            paymentParams.put("expend", "expend");
            paymentParams.put("notify_url", "notify_url");
            Map<String, Object> payment = Payment.close(paymentParams);
            return ResultMap.ok()
                    .put("data", payment)
                    ;
        } catch (BaseAdaPayException e) {
            e.printStackTrace();
        }
        System.out.println("=======close payment end=======");
        return ResultMap.error(-2, errMsg);
    }

    public static void main(String[] args) throws Exception {
//        String tradeNo  = "GU202206081400199998";
        PaymentRequestDto paymentRequestDto = new PaymentRequestDto();
        paymentRequestDto.setBody("test");
//        paymentRequestDto.setOrderNo(tradeNo);
        paymentRequestDto.setOrderNo(RandomUtil.getRandomOld(RandomUtil.GROUP_USER_ORDER));
        paymentRequestDto.setTotalAmount(new BigDecimal("0.01"));
        paymentRequestDto.setCreateOrderTime(new Date());
        paymentRequestDto.setPayWay("alipay");
        HfPayServiceImpl h = new HfPayServiceImpl();
        h.init();
        Map<String, Object> stringObjectMap = h.tradeCreate(paymentRequestDto);
        log.info(" 下单返回数据：{} ",stringObjectMap);
        paymentRequestDto.setCreateOrderTime(new Date());
//        Map<String, Object> stringObjectMap2 = h.tradeCreate(paymentRequestDto);
//        log.info(" 下单2返回数据：{} ",stringObjectMap2);
//        paymentRequestDto.setMerOrderId("002112022060718112010380190186975551488");
//        Map<String, Object> reverse = h.reverse(paymentRequestDto);
//        log.info(" 撤销订单返回数据：{} ",reverse);
//        Map<String, Object> queryReverse = h.queryReverse("");
//        log.info(" 撤单查询：{} ",queryReverse);

//        tradeNo = "002112022060814001410380489386883682304";
//        PaymentInfoResponseDto queryOrder = h.queryOrder(null, null, tradeNo);
//        log.info(" 查询订单返回数据：{} ",queryOrder);
//        RefundRequestDto refundRequestDto = new RefundRequestDto();
//        String randomOld = RandomUtil.getRandomOld(RandomUtil.REFUND_NO);
//        refundRequestDto.setTradeNo(tradeNo);
//        refundRequestDto.setRefundAmount(new BigDecimal("0.01"));
//        refundRequestDto.setRefundNo(randomOld);
//        ResultMap resultMap = h.refund(refundRequestDto);
//        log.info(" 退款返回数据：{} ",resultMap);
//        ResultMap refundResult = h.queryRefund(null, null, "RN202206071807072015");
//        log.info(" 退款返回结果：{} ",refundResult);
//        System.out.println(stringObjectMap);
    }


}
