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

import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.JeepayClient;
import com.jeequan.jeepay.model.PayOrderCreateReqModel;
import com.jeequan.jeepay.model.PayOrderQueryReqModel;
import com.jeequan.jeepay.model.RefundOrderCreateReqModel;
import com.jeequan.jeepay.model.RefundOrderQueryReqModel;
import com.jeequan.jeepay.request.PayOrderCreateRequest;
import com.jeequan.jeepay.request.PayOrderQueryRequest;
import com.jeequan.jeepay.request.RefundOrderCreateRequest;
import com.jeequan.jeepay.request.RefundOrderQueryRequest;
import com.jeequan.jeepay.response.PayOrderCreateResponse;
import com.jeequan.jeepay.response.PayOrderQueryResponse;
import com.jeequan.jeepay.response.RefundOrderCreateResponse;
import com.jeequan.jeepay.response.RefundOrderQueryResponse;
import com.tzy.common.dto.IpAddrDTO;
import com.tzy.common.utils.Base64Util;
import com.tzy.common.utils.IpUtils;
import com.tzy.common.utils.LogSyncUtil;
import com.tzy.common.utils.ServletUtils;
import com.tzy.framework.pay.config.QmPayConfig;
import com.tzy.framework.pay.dto.PaymentInfoResponseDto;
import com.tzy.framework.pay.dto.PaymentRequestDto;
import com.tzy.framework.pay.dto.RefundRequestDto;
import com.tzy.framework.pay.dto.ResultMap;
import com.tzy.framework.pay.service.Qme1PayService;
import com.tzy.framework.pay.util.bofoo.bank.HttpUtil;
import com.tzy.framework.util.RandomUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 全民 易一 支付
 */
@Slf4j
@Service
public class Qme1PayServiceImpl implements Qme1PayService {

//    private String apiHost = "https://payapi.e1tech.cn";
    private String apiHost = "https://payapi.proxy.sygorun.com";

    /**
     * 统一下单
     * @param payRequestBody
     * @return
     */
    public ResultMap tradeCreate(PaymentRequestDto payRequestBody){
        ResultMap resultMap = new ResultMap();
        try{
            String payWay = payRequestBody.getPayWay();
            QmPayConfig qmPayConfig = (QmPayConfig) payRequestBody.getPayConfigByClass( QmPayConfig.class);
//            boolean isSub = payRequestBody.getPayConfig().getBooleanValue("isSub");
            String body = String.valueOf(payRequestBody.getBody());
            if(StringUtils.isNotEmpty(body) ){
                body = Base64Util.subStringByBytes(body,80)+"...";
            }
            String subject = "集换式卡牌";
            String merchantOrderId = RandomUtil.getRandomNew(RandomUtil.GROUP_USER_ORDER);
            JeepayClient jeepayClient = JeepayClient.getInstance(qmPayConfig.getAppId(), qmPayConfig.getAppkey(), apiHost);
            // 构建请求数据
            PayOrderCreateReqModel model = new PayOrderCreateReqModel();
            model.setExpiredTime(String.valueOf(payRequestBody.getExpireTime().getTime()-payRequestBody.getCreateOrderTime().getTime()));
            // 商户号
            model.setMchNo(qmPayConfig.getMid());
            // 应用ID
            model.setAppId(jeepayClient.getAppId());
            // 商户订单号
            model.setMchOrderNo(merchantOrderId);
            // 支付方式
            model.setWayCode(payRequestBody.getPaySubWay());
            // 金额，单位分
            model.setAmount(payRequestBody.getTotalAmount().multiply(new BigDecimal(100)).longValue());
            // 币种，目前只支持cny
            model.setCurrency("CNY");
            // 发起支付请求客户端的IP地址
            String ipAddr = IpUtils.getIpAddr(ServletUtils.getRequest());
            if(StringUtils.isNotEmpty(ipAddr)) {
                String[] ipArray = ipAddr.split(",");
                String ip = ipArray[0];
                model.setClientIp(ip);
            }else{
                return ResultMap.error("下单失败[IP异常]！");
            }
            // 商品标题
            model.setSubject(subject);
            // 商品描述
            model.setBody(body);
            // 后台服务器回调地址，
            model.setNotifyUrl(qmPayConfig.getPayNotifyUrl());
            model.setExtParam(payWay);//扩展参数验证支付方式
            PayOrderCreateRequest request = new PayOrderCreateRequest();
            request.setBizModel(model);
            log.info(" 请求参数：{} ",JSONObject.toJSONString(request));
            // 发起统一下单
            LogSyncUtil.logSync("全民易一支付 预下单,交易编号:{},请求参数:{}",payRequestBody.getOrderNo(),request);
            PayOrderCreateResponse response = jeepayClient.execute(request);
            LogSyncUtil.logSync("全民易一支付 预下单,交易编号:{},返回结果:{}",payRequestBody.getOrderNo(),response);
            log.info(" 统一下单返回结果：{} ",response);
            // 验证返回数据签名
            if(response.checkSign(qmPayConfig.getAppkey())) {
                // 判断下单是否返回成功
                if(response.isSuccess(qmPayConfig.getAppkey())){
                    JSONObject data = response.getData();
                    String payData = data.getString("payData");
                    resultMap.put("merOrderId",merchantOrderId);
                    resultMap.put("orderNo",payRequestBody.getOrderNo());
                    resultMap.put("qrcode",payData);
                    data.put("merOrderId",merchantOrderId);
                    data.put("url",payData);
                    resultMap.put("data",data);
                    return resultMap;
                } else {
                    return ResultMap.error(response.getMsg());
                }
            } else {
                return ResultMap.error("签名验证失败");
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
        }
        return ResultMap.error("下单失败");
    }

    /**
     * 支付查询
     * @param payRequestBody
     * @return
     */
    public PaymentInfoResponseDto queryOrder(PaymentRequestDto payRequestBody) {
        PaymentInfoResponseDto paymentInfoResponseDto = new PaymentInfoResponseDto();
        String errMsg = "";
        try{
            String payWay = payRequestBody.getPayWay();
            String orderNo = payRequestBody.getOrderNo();
            QmPayConfig qmPayConfig = (QmPayConfig) payRequestBody.getPayConfigByClass(QmPayConfig.class);
            JeepayClient jeepayClient = JeepayClient.getInstance(qmPayConfig.getAppId(), qmPayConfig.getAppkey(), apiHost);
            PayOrderQueryRequest request = new PayOrderQueryRequest();
            PayOrderQueryReqModel model = new PayOrderQueryReqModel();
            model.setAppId(qmPayConfig.getAppId());//应⽤ID
            model.setMchNo(qmPayConfig.getMid());//商户号
            model.setMchOrderNo(orderNo);//商户订单号
            request.setBizModel(model);
            log.info(" 请求参数：{} ",JSONObject.toJSONString(request));
            // 发起统一下单
//            PayOrderQueryResponse response = jeepayClient.execute(request);
            LogSyncUtil.logSync("全民易一支付 查询,交易编号:{},请求参数:{}",payRequestBody.getOrderNo(),request);
            PayOrderQueryResponse response = jeepayClient.execute(request);
            LogSyncUtil.logSync("全民易一支付 查询,交易编号:{},返回结果:{}",payRequestBody.getOrderNo(),response);
            log.info(" 统一下单返回结果：{} ",response);
            // 验证返回数据签名
            if(response.checkSign(qmPayConfig.getAppkey())) {
                // 判断下单是否返回成功
                if(response.isSuccess(qmPayConfig.getAppkey())){
                    JSONObject data = response.getData();
                    if(data.getInteger("state") == 2){
                        paymentInfoResponseDto.setSuccess(true);
                        paymentInfoResponseDto.setOrderNo(orderNo);
                        paymentInfoResponseDto.setPayWay(payWay);
                        paymentInfoResponseDto.setPaymentNo(data.getString("payOrderId"));
                        paymentInfoResponseDto.setPaymentPrice(new BigDecimal(data.getString("amount")).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN));
                        paymentInfoResponseDto.setActualPayment(new BigDecimal(data.getString("amount")).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_DOWN));
                        paymentInfoResponseDto.setPaymentSuccessTime(new Date(data.getLong("successTime")));
//                        paymentInfoResponseDto.setPaymentSuccessTime(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, data.getString("successTime")));
                        return paymentInfoResponseDto;
                    }else{
                        return PaymentInfoResponseDto.error(-1,getPayStateMsg(data.getInteger("state")));
                    }
                } else {
                    return PaymentInfoResponseDto.error(-1,response.getMsg());
                }
            } else {
                return PaymentInfoResponseDto.error(-1,"签名验证失败");
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
            errMsg = "下单失败";
        }
        return PaymentInfoResponseDto.error(-2,errMsg);
    }

    /**
     * 退款
     * @param refundRequestDto
     * @return
     */
    public ResultMap refund(RefundRequestDto refundRequestDto) {
        String errMsg = "";
        try{
            QmPayConfig qmPayConfig = (QmPayConfig) refundRequestDto.getPayConfigByClass(QmPayConfig.class);
            JeepayClient jeepayClient = JeepayClient.getInstance(qmPayConfig.getAppId(), qmPayConfig.getAppkey(), apiHost);
            RefundOrderCreateReqModel model = new RefundOrderCreateReqModel();
            String refundOrderId = RandomUtil.getRandomOld(RandomUtil.REFUND_NO);
            model.setAppId(qmPayConfig.getAppId());
            model.setMchNo(qmPayConfig.getMid());
            model.setMchRefundNo(refundOrderId);//退款编码
            model.setMchOrderNo(refundRequestDto.getOrderNo());//商户订单号
            model.setRefundAmount(refundRequestDto.getRefundAmount().multiply(new BigDecimal(100)).longValue());//退款金额
            model.setCurrency("cny");//货币代码
            model.setRefundReason(refundRequestDto.getRefundMsg());//退款原因
            model.setExtParam(refundRequestDto.getPayWay());//扩展参数
            RefundOrderCreateRequest  request = new RefundOrderCreateRequest();
            request.setBizModel(model);
            log.info(" 请求参数：{} ",JSONObject.toJSONString(request));
            // 发起统一下单
//            RefundOrderCreateResponse response = jeepayClient.execute(request);
            LogSyncUtil.logSync("全民易一支付 退款,交易编号:{},请求参数:{}",refundRequestDto.getOrderNo(),request);
            RefundOrderCreateResponse response = jeepayClient.execute(request);
            LogSyncUtil.logSync("全民易一支付 退款,交易编号:{},返回结果:{}",refundRequestDto.getOrderNo(),response);
            log.info(" 退款返回结果：{} ",response);
            // 验证返回数据签名
            if(response.checkSign(qmPayConfig.getAppkey())) {
                // 判断下单是否返回成功
                if(response.isSuccess(qmPayConfig.getAppkey())){
                    JSONObject data = response.getData();
                    if(data.getInteger("state") == 2){
                        Map<String, String> stringStringMap = new HashMap<>();
                        stringStringMap.put("out_refund_no", refundOrderId);
                        stringStringMap.put("refund_id", data.getString("refundOrderId"));
                        stringStringMap.put("refund_fee", String.valueOf(model.getRefundAmount()));
                        stringStringMap.put("fund_change", "Y");
                        stringStringMap.put("refund_status","SUCCESS");
                        return  ResultMap.ok()
                                .put("data",stringStringMap)
                                ;
                    }else{
                        return ResultMap.error(-1,getRefundStateMsg(data.getInteger("state")));
                    }
                } else {
                    return ResultMap.error(-1,response.getMsg());
                }
            } else {
                return ResultMap.error(-1,"签名验证失败");
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
            errMsg = "退款请求失败";
        }
        return ResultMap.error(-2,errMsg);
    }

    /**
     * 退款 查询
     * @param refundRequestDto
     * @return
     */
    public ResultMap refundQuery(RefundRequestDto refundRequestDto) {
        String errMsg = "";
        try{
            QmPayConfig qmPayConfig = (QmPayConfig) refundRequestDto.getPayConfigByClass(QmPayConfig.class);
            JeepayClient jeepayClient = JeepayClient.getInstance(qmPayConfig.getAppId(), qmPayConfig.getAppkey(), apiHost);
            RefundOrderQueryReqModel model = new RefundOrderQueryReqModel();
            model.setMchRefundNo(refundRequestDto.getRefundNo());//退款编码
            model.setAppId(qmPayConfig.getAppId());
            model.setMchNo(qmPayConfig.getMid());
            RefundOrderQueryRequest request = new RefundOrderQueryRequest();
            request.setBizModel(model);
            log.info(" 请求参数：{} ",JSONObject.toJSONString(request));
            // 发起统一下单
//            RefundOrderQueryResponse response = jeepayClient.execute(request);
            LogSyncUtil.logSync("全民易一支付 退款查询,交易编号:{},请求参数:{}",refundRequestDto.getRefundNo(),request);
            RefundOrderQueryResponse response = jeepayClient.execute(request);
            LogSyncUtil.logSync("全民易一支付 退款查询,交易编号:{},返回结果:{}",refundRequestDto.getRefundNo(),response);
            log.info(" 退款 查询返回结果：{} ",response);
            // 验证返回数据签名
            if(response.checkSign(qmPayConfig.getAppkey())) {
                // 判断下单是否返回成功
                if(response.isSuccess(qmPayConfig.getAppkey())){
                    JSONObject data = response.getData();
                    if(data.getInteger("state") == 2){
                        Map<String, String> stringStringMap = new HashMap<>();
                        stringStringMap.put("out_refund_no", refundRequestDto.getRefundNo());
                        stringStringMap.put("refund_id", data.getString("refundOrderId"));
                        stringStringMap.put("refund_fee", String.valueOf(data.getInteger("refundAmount")));
                        stringStringMap.put("fund_change", "Y");
                        return  ResultMap.ok()
                                .put("data",stringStringMap)
                                ;
                    }else{
                        return ResultMap.error(-1,getRefundStateMsg(data.getInteger("state")));
                    }
                } else {
                    return ResultMap.error(-1,response.getMsg());
                }
            } else {
                return ResultMap.error(-1,"签名验证失败");
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error(e.getMessage());
            errMsg = "退款请求失败";
        }
        return ResultMap.error(-2,errMsg);
    }


    private String getPayStateMsg(Integer state){
        String stateMsg = "下单失败[-1]";
        switch (state){
            case 0:
                stateMsg = "待支付[0]";
                break;
            case 1:
                stateMsg = "⽀付中[1]";
                break;
            case 2:
                stateMsg = "⽀付成功[2]";
                break;
            case 3:
                stateMsg = "⽀付失败[3]";
                break;
            case 4:
                stateMsg = "已撤销[4]";
                break;
            case 5:
                stateMsg = "已退款[5]";
                break;
            case 6:
                stateMsg = "订单关闭[6]";
                break;
        }
        return stateMsg;
    }

    private String getRefundStateMsg(Integer state){
        String stateMsg = "下单失败[-1]";
        switch (state){
            case 0:
                stateMsg = "退款中[0]";
                break;
            case 1:
                stateMsg = "退款中[1]";
                break;
            case 2:
                stateMsg = "退款成功[2]";
                break;
            case 3:
                stateMsg = "退款失败[3]";
                break;
            case 4:
                stateMsg = "退款关闭[4]";
                break;
        }
        return stateMsg;
    }

}
