package com.hzs.third.pay.controller.notify;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hzs.common.core.enums.EPayChannel;
import com.hzs.common.core.enums.EPayType;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.third.pay.config.JdPayConfig;
import com.hzs.third.pay.constants.JdPayConstants;
import com.hzs.third.pay.controller.base.JdBaseController;
import com.hzs.third.pay.dto.jd.JdPayNotifyBody;
import com.hzs.third.pay.jdpay.dto.JdPayTradeSuccessNotify;
import com.hzs.third.pay.jdpay.sdk.JdPay;
import com.hzs.third.pay.jdpay.util.GsonUtil;
import com.hzs.third.pay.service.IPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 京东支付回调控制器
 */
@Slf4j
@RestController
@RequestMapping("/jd")
public class JdPayNotifyController extends JdBaseController {

    @Autowired
    private JdPayConfig jdPayConfig;
    @Autowired
    private IPayService iPayService;

    /**
     * 京东支付回调
     *
     * @param request
     */
    @PostMapping("/notify")
    public String notify(HttpServletRequest request) {
        try {
            String reqBody = this.getRequestBody(request);
            log.info("京东支付回调！ body： {}", reqBody);

            if (this.checkToken(request, reqBody, jdPayConfig.getSecretKey())) {
                // 签名校验通过
                JdPayNotifyBody notifyBody = JSONUtil.toBean(reqBody, JdPayNotifyBody.class);

                // 支付流水号
                String payNumber = notifyBody.getOrderNum();
                // 支付时间
                Date payTime = DateUtils.parseDate(notifyBody.getCompleteTime(), DateUtils.YYYY_MM_DD_HH_MM_SS);
                // 支付金额
                BigDecimal payMoney = new BigDecimal(notifyBody.getOrderAmount());

                // 支付扩展类型
                String type = notifyBody.getExtraInfo();

                // 回调订单编号
                String thirdOrderCode = notifyBody.getRequestNum();
                // 支付信息编号
                String orderCode = thirdOrderCode;
                // 处理订单号以及扩展类型
                if (orderCode.indexOf("-") > 0) {
                    // 带有分隔，需要处理
                    orderCode = orderCode.split("-")[0];
                }

                // 支付后续业务处理
                if (iPayService.notifyHandle(type, orderCode, thirdOrderCode, payNumber, payTime, payMoney, EPayChannel.JD, "")) {
                    return JdPayConstants.RETURN_SUCCESS;
                }
            } else {
                log.error("京东支付回调签名校验失败！");
            }
        } catch (Exception e) {
            log.error("京东支付回调处理异常", e);
        }
        return JdPayConstants.RETURN_FAIL;
    }


    @Resource(name = "jdPayBank")
    private JdPay jdPay;

    /**
     * 京东收银台处理成功返回
     */
    private static final String SUCCESS = "SUCCESS";
    /**
     * 京东收银台处理失败返回
     */
    private static final String ERROR = "ERROR";

    /**
     * 京东收银台异步支付回调
     *
     * @param reqText
     * @return 成功返回"SUCCESS",  失败返回"ERROR",京东支付会再次发起通知，通知频次见接口文档。
     */
    @PostMapping("/trade-notify")
    public String tradeNotify(@RequestBody String reqText) {
        log.info("京东收银台支付异步回调！ reqText： {}", reqText);
        try {
            // 验证签名与解密
            String interData = jdPay.verifyResponse(reqText);
            JdPayTradeSuccessNotify successNotify = GsonUtil.fromJson(interData, JdPayTradeSuccessNotify.class);
            if (null != successNotify) {
                if ("FINI".equals(successNotify.getTradeStatus())) {
                    // 支付成功处理

                    // 商户订单号
                    String payNumber = successNotify.getTradeNo();
                    // 渠道流水号
                    String channelNumber = "";
                    // 支付完成时间
                    Date payTime = DateUtils.parseDateOne(successNotify.getFinishDate(), DateUtils.YAMMERERS);
                    // 支付扩展类型
                    String type = successNotify.getReturnParams();

                    // 回调订单编号
                    String thirdOrderCode = successNotify.getOutTradeNo();
                    // 订单编号
                    String orderCode = thirdOrderCode;
                    String acqOrderId = successNotify.getAcqOrderId();

                    // 订单金额
                    int tradeAmount = Integer.parseInt(successNotify.getTradeAmount());
                    BigDecimal payMoney = new BigDecimal(tradeAmount).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
                    Integer payType = convertPayType(successNotify.getPayTool());
                    // 支付后续业务处理
                    if (iPayService.notifyHandle(type, orderCode, thirdOrderCode, payNumber, payTime, payMoney, EPayChannel.JD, channelNumber, payType, acqOrderId)) {
                        return SUCCESS;
                    }
                } else {
                    log.error("京东收银台支付异步回调失败，resultDesc: {}", successNotify.getResultDesc());
                }
            } else {
                log.error("京东收银台支付异步回调解密为空");
            }
        } catch (Exception e) {
            log.error("京东收银台支付异步回调异常", e);
        }
        return ERROR;
    }
    private Integer convertPayType(String payName){
        if(StrUtil.isEmpty(payName)){
            payName = "";
        }
        Integer result = EPayType.WECHAT.getValue();
        switch (payName){
            case "XJK":
                result = EPayType.MINI_TREASURY.getValue();
                break;
            case "JIOU":
                result = EPayType.CREDIT_LINE.getValue();
                break;
            case "SJIOU":
                result = EPayType.SUPER_CREDIT_LINE.getValue();
                break;
            case "ACCT":
                result = EPayType.WALLET_BALANCE.getValue();
                break;
            case "EXPR":
                result = EPayType.BANK_CARD.getValue();
                break;
            case "WX":
                result = EPayType.WECHAT.getValue();
                break;
            case "ALIPAY":
                result = EPayType.ALIPAY.getValue();
                break;
            case "YSF":
                result = EPayType.CLOUD_PAY.getValue();
                break;

        }
        return result;
    }


    /**
     * 京东收银台页面回调
     *
     * @param request
     * @return
     */
    @PostMapping("/sync-notify")
    public String syncNotify(HttpServletRequest request) {
        // 签名验证逻辑，需要支持添加通知字段不影响结果
        Map<String, String> respMap = getAllRequestParam(request);
        log.info("京东收银台支付页面回调！ request: {}", respMap);

        try {
            if (jdPay.verifyPageCallBack(respMap)) {
                if ("FINI".equals(respMap.get("status"))) {
                    // todo 支付成功

                    return SUCCESS;
                } else if ("WPAR".equals(respMap.get("status"))) {
                    // todo 支付处理中
                    log.error("京东支付页面回调，支付处理中");
                } else {
                    // todo 支付失败
                    log.error("京东支付页面回调，支付失败");
                }
            } else {
                // 签名异常，报错
                log.error("京东收银台支付页面回调！签名异常！");
            }
        } catch (Exception e) {
            log.error("京东支付页面回调参数", e);
        }
        return ERROR;
    }

    /**
     * 获取客户端请求参数中所有的信息
     */
    private Map<String, String> getAllRequestParam(final HttpServletRequest request) {
        Map<String, String> respMap = new HashMap<>();
        Enumeration<?> temp = request.getParameterNames();
        if (null != temp) {
            while (temp.hasMoreElements()) {
                String en = (String) temp.nextElement();
                String value = request.getParameter(en);
                respMap.put(en, value);
                //如果字段的值为空，判断若值为空，则删除这个字段>
                if (null == respMap.get(en) || "".equals(respMap.get(en))) {
                    respMap.remove(en);
                }
            }
        }
        return respMap;
    }

}
