package com.xingxi.unifiedpay.open;

import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
import com.github.binarywang.wxpay.service.WxPayService;
import com.xingxi.business.Order.domain.Order;
import com.xingxi.business.Order.domain.OrderDetail;
import com.xingxi.business.PaymentInfo.domain.PaymentInfo;
import com.xingxi.common.enums.EOrderDetailStatus;
import com.xingxi.common.enums.EOrderStatus;
import com.xingxi.common.mapper.XingxiUnifiedpayExtMapper;
import com.xingxi.common.mq.bo.order.OrderBO;
import com.xingxi.common.mq.publisher.order.OrderPayedMqPublisher;
import com.xingxi.common.service.XingxiUnifiedpayCallbackDTO;
import com.xingxi.unifiedpay.bean.BiandanUnifiedpayCallbackRequest;
import com.xingxi.unifiedpay.bean.BiandanUnifiedpayCallbackResponse;
import com.xingxi.unifiedpay.domain.XingxiUnifiedpayCallbackResultDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.List;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/unifiedpay")
@ConditionalOnBean({XingxiUnifiedpayServiceI.class})
public class WXPayCallbackEndpoint {

    private final XingxiUnifiedpayServiceI unifiedpayServiceI;
    private final WxPayService wxPayService;
    private final XingxiUnifiedpayExtMapper xingxiUnifiedpayExtMapper;
    private final OrderPayedMqPublisher orderPayedMqPublisher;

    @PostMapping("/wxpay/callback")
    public String callback(HttpServletRequest request, HttpServletResponse response) {
        log.debug("WXPayCallback");

        try {

            SignatureHeader signatureHeader = httpRequestToSignatureHeader(request);
            String s = StreamUtils.copyToString(request.getInputStream(), Charset.defaultCharset());

            WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = wxPayService.parseOrderNotifyV3Result(s, signatureHeader);
            WxPayOrderNotifyV3Result.DecryptNotifyResult decryptNotifyResult = wxPayOrderNotifyV3Result.getResult();

            XingxiUnifiedpayCallbackResultDTO xingxiUnifiedpayCallbackResultDTO = decryptNotifyResultToBiandanUnifiedpayCallbackResultDTO(decryptNotifyResult);

            XingxiUnifiedpayCallbackDTO xingxiUnifiedpayCallbackDTO = new XingxiUnifiedpayCallbackDTO();
            BeanUtils.copyProperties(xingxiUnifiedpayCallbackResultDTO, xingxiUnifiedpayCallbackDTO);

            String tradeState = xingxiUnifiedpayCallbackResultDTO.getTradeState();
            String outTradeNo = xingxiUnifiedpayCallbackResultDTO.getOutTradeNo();
            String callUnifiedpayComponent = xingxiUnifiedpayCallbackResultDTO.getCallUnifiedpayComponent();

            PaymentInfo dbPaymentInfo = xingxiUnifiedpayExtMapper.selectLockPaymentInfoByOutTradeNo(outTradeNo);
            if (dbPaymentInfo != null && "SUCCESS".equals(tradeState)) {
                dbPaymentInfo.setUpdateUser(callUnifiedpayComponent);
                dbPaymentInfo.setUpdateTime(new Date());
                updatePaymentInfo(dbPaymentInfo, xingxiUnifiedpayCallbackDTO);
                Long orderId = dbPaymentInfo.getOrderId();

                // lock
                Order dbOrder = xingxiUnifiedpayExtMapper.selectLockOrderByOrderId(orderId);
                dbOrder.setUpdateTime(dbPaymentInfo.getUpdateTime());
                dbOrder.setUpdateUser(dbPaymentInfo.getUpdateUser());

                updateOrderStatus(dbOrder);

                // 发送订单支付完成事件消息
                orderPayedEvent(dbOrder);

            }

        } catch (Exception e) {
            log.debug("处理微信支付回调通知失败!!!!");
            return "FAIL";
        }

        return "SUCCESS";
    }

    private void updatePaymentInfo(PaymentInfo dbPaymentInfo, XingxiUnifiedpayCallbackDTO biandanUnifiedpayCallbackDTO) {
        String tradeState = biandanUnifiedpayCallbackDTO.getTradeState();
        String tradeType = biandanUnifiedpayCallbackDTO.getTradeType();
        String bankType = biandanUnifiedpayCallbackDTO.getBankType();
        String transactionId = biandanUnifiedpayCallbackDTO.getTransactionId();
        String callUnifiedpayComponent = biandanUnifiedpayCallbackDTO.getCallUnifiedpayComponent();

        PaymentInfo updatePaymentInfo = new PaymentInfo();
        updatePaymentInfo.setPayId(dbPaymentInfo.getPayId());
        updatePaymentInfo.setTradeType(tradeType);
        updatePaymentInfo.setTradeState(tradeState);
        updatePaymentInfo.setTransactionId(transactionId);
        updatePaymentInfo.setSuccessTime(new Date());
        updatePaymentInfo.setPayTime(updatePaymentInfo.getSuccessTime());
        updatePaymentInfo.setBankType(bankType);
        updatePaymentInfo.setUpdateUser(callUnifiedpayComponent);
        updatePaymentInfo.setUpdateTime(dbPaymentInfo.getUpdateTime());
        xingxiUnifiedpayExtMapper.updatePaymentInfo(updatePaymentInfo);
    }

    private SignatureHeader httpRequestToSignatureHeader(HttpServletRequest request){

        String serial = request.getHeader("Wechatpay-Serial");
        String signature = request.getHeader("Wechatpay-Signature");
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String nonceStr = request.getHeader("Wechatpay-Nonce");
        SignatureHeader signatureHeader = new SignatureHeader();
        signatureHeader.setSerial(serial);
        signatureHeader.setSignature(signature);
        signatureHeader.setNonce(nonceStr);
        signatureHeader.setTimeStamp(timestamp);
        return signatureHeader;

    }

    private XingxiUnifiedpayCallbackResultDTO decryptNotifyResultToBiandanUnifiedpayCallbackResultDTO(WxPayOrderNotifyV3Result.DecryptNotifyResult decryptNotifyResult) {
        String tradeState = decryptNotifyResult.getTradeState();
        String outTradeNo = decryptNotifyResult.getOutTradeNo();
        String successTimeString = decryptNotifyResult.getSuccessTime();
        String tradeType = decryptNotifyResult.getTradeType();
        String bankType = decryptNotifyResult.getBankType();
        String attach = decryptNotifyResult.getAttach();
        String transactionId = decryptNotifyResult.getTransactionId();

        XingxiUnifiedpayCallbackResultDTO biandanUnifiedpayCallbackResultDTO = new XingxiUnifiedpayCallbackResultDTO();
        biandanUnifiedpayCallbackResultDTO.setTradeState(tradeState);
        biandanUnifiedpayCallbackResultDTO.setOutTradeNo(outTradeNo);
        biandanUnifiedpayCallbackResultDTO.setSuccessTimeString(successTimeString);
        biandanUnifiedpayCallbackResultDTO.setTradeType(tradeType);
        biandanUnifiedpayCallbackResultDTO.setBankType(bankType);
        biandanUnifiedpayCallbackResultDTO.setAttach(attach);
        biandanUnifiedpayCallbackResultDTO.setTransactionId(transactionId);
        biandanUnifiedpayCallbackResultDTO.setCallUnifiedpayComponent("WXPayCallback");

        biandanUnifiedpayCallbackResultDTO.setOriginalObj(decryptNotifyResult);
        return biandanUnifiedpayCallbackResultDTO;

    }

    private void updateOrderStatus(Order dbOrder) {
        Order updateOrderStatus = new Order();
        updateOrderStatus.setOrderId(dbOrder.getOrderId());
        updateOrderStatus.setOrderStatus(EOrderStatus.PAYED.getVal());
        updateOrderStatus.setUpdateUser(dbOrder.getUpdateUser());
        updateOrderStatus.setUpdateTime(dbOrder.getUpdateTime());
        xingxiUnifiedpayExtMapper.updateOrder(updateOrderStatus);

        OrderDetail queryOrderDetail = new OrderDetail();
        queryOrderDetail.setOrderId(dbOrder.getOrderId());
        List<OrderDetail> orderDetails = xingxiUnifiedpayExtMapper.selectOrderDetailList(queryOrderDetail);
        for (OrderDetail dbOrderDetail : orderDetails) {
            OrderDetail updateOrderDetailStatus = new OrderDetail();
            updateOrderDetailStatus.setOrderDetailId(dbOrderDetail.getOrderDetailId());
            updateOrderDetailStatus.setOrderDetailStatus(EOrderDetailStatus.APPROVED.getVal());
            updateOrderDetailStatus.setUpdateUser(dbOrder.getUpdateUser());
            updateOrderDetailStatus.setUpdateTime(dbOrder.getUpdateTime());
            xingxiUnifiedpayExtMapper.updateOrderDetail(updateOrderDetailStatus);
        }
    }

    private void orderPayedEvent(Order orderDTO) {
        // EDIT_ROUTE_FOR_PAYED
        // EDIT_EXCHANGE
        OrderBO orderBO = new OrderBO();
        orderBO.setOrderId(orderDTO.getOrderId());
        orderBO.setOrderNo(orderDTO.getOrderNo());
        orderPayedMqPublisher.sendMessage(orderBO);
    }
//
//    @PostMapping("/wxpay/refund/callback")
//    public String refund(HttpServletRequest request, HttpServletResponse response) {
//        log.debug("WXPayRefundCallback");
//
//        try {
//            SignatureHeader signatureHeader = httpRequestToSignatureHeader(request);
//            String s = StreamUtils.copyToString(request.getInputStream(), Charset.defaultCharset());
//
//            WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = wxPayService.parseOrderNotifyV3Result(s, signatureHeader);
//            WxPayOrderNotifyV3Result.DecryptNotifyResult decryptNotifyResult = wxPayOrderNotifyV3Result.getResult();
//
//            XingxiUnifiedpayCallbackResultDTO xingxiUnifiedpayCallbackResultDTO = decryptNotifyResultToBiandanUnifiedpayCallbackResultDTO(decryptNotifyResult);
//
//
//
//
//
//        } catch (Exception e) {
//
//            log.debug("处理微信支付回调通知失败!!!!" + e.getMessage());
//            return "FAIL";
//        }
//
//        return "SUCCESS";
//    }
}
