package com.yn.bftl.thirdparty.modules.unionpay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.yn.bftl.common.common.exception.YnceError;
import com.yn.bftl.common.common.util.RouteUtil;
import com.yn.bftl.common.modules.account.entity.Payment;
import com.yn.bftl.common.modules.configuration.entity.ThirdPartyPaySet;
import com.yn.bftl.common.modules.order.dto.IRefundDTO;
import com.yn.bftl.common.modules.order.entity.Order;
import com.yn.bftl.common.modules.order.enums.*;
import com.yn.bftl.common.modules.order.vo.OrderOnlinePayVO;
import com.yn.bftl.thirdparty.common.exception.YnceErrorException;
import com.yn.bftl.thirdparty.common.repository.OrderRepository;
import com.yn.bftl.thirdparty.common.repository.PaymentRepository;
import com.yn.bftl.thirdparty.common.service.BaseMemberService;
import com.yn.bftl.thirdparty.common.util.HttpClientUtil;
import com.yn.bftl.thirdparty.modules.business.service.SubaccountService;
import com.yn.bftl.thirdparty.modules.business.util.ThirdPartyConfigUtil;
import com.yn.bftl.thirdparty.modules.unionpay.dto.UnionpayAppOrderDTO;
import com.yn.bftl.thirdparty.modules.unionpay.service.UmsPayService;
import com.yn.bftl.thirdparty.modules.unionpay.service.UnionpayService;
import com.yn.bftl.thirdparty.modules.unionpay.util.UnionpayUtil;
import com.yn.bftl.thirdparty.modules.unionpay.vo.base.UnionpayResponseVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Map;

/**
 * @author huabiao
 * @create 2022/8/30  15:15
 **/
@Slf4j
@Service
public class UnionpayServiceImpl extends BaseMemberService implements UnionpayService {

    @Resource
    private OrderRepository orderRepository;
    @Resource
    private PaymentRepository paymentRepository;
    @Resource
    private UnionpayUtil unionpayUtil;
    @Resource
    private UmsPayService umsPayService;
    @Resource
    private SubaccountService subaccountService;
    @Resource
    private ThirdPartyConfigUtil thirdPartyConfigUtil;

    @Override
    public Map<String, Object> appOrder(UnionpayAppOrderDTO unionpayAppOrderDTO) {
        Order order = orderRepository.findById(unionpayAppOrderDTO.getOrderId())
                .orElseThrow(() -> new YnceErrorException(YnceError.YNCE_204003));
        if (!OrderStatus.CREATED.equals(order.getOrderStatus())) {
            throw new YnceErrorException("订单" + order.getOrderStatus().getName());
        }
        if (!order.getApprovalStatus().equals(ApprovalStatus.APPROVE)) {
            throw new YnceErrorException(YnceError.YNCE_204016);
        }
        if (!order.getPaymentStatus().equals(PaymentStatus.UN_PAID)) {
            throw new YnceErrorException(YnceError.YNCE_204015);
        }

        // 创建支付单
        String unionpaySn = unionpayUtil.generateUnionpaySn(Order.class, order.getConsignmentCompany() != null ? order.getConsignmentCompany().getId() : order.getSellerCompany().getId());
        log.info("银联支付单号：{}", unionpaySn);
        String paymentSn = subaccountService.createPayment(order, null, unionpayAppOrderDTO.getType(), unionpaySn, null, null);
        switch (unionpayAppOrderDTO.getType()) {
            case WECHAT:
            case ALIPAY:
            case CHINA_UNIONPAY_QUICK_PASS:
                Map<String, Object> result = umsPayService.appPreOrder(order, unionpaySn, unionpayAppOrderDTO.getType());
                result.put("paymentSn", paymentSn);
                return result;
            case POS:
                throw new YnceErrorException("此接口不支持POS支付方式！");
            default:
                throw new YnceErrorException("还未支持此支付方式！");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public UnionpayAppTradeStatus orderQuery(String unionpaySn) {
        Payment payment = paymentRepository.findByUnionpaySn(unionpaySn);
        if (payment == null) {
            throw new YnceErrorException(YnceError.YNCE_205007);
        }
        if (PayStatus.SUCC.equals(payment.getPayStatus())) {
            return UnionpayAppTradeStatus.TRADE_SUCCESS;
        }
        String route = RouteUtil.ROUTE_UNIONPAY_NETPAY_QUERY;
        if (payment.getPaymentMethod().equals(PaymentMethod.ALIPAY)) {
            route = RouteUtil.ROUTE_UNIONPAY_NETPAY_QUERY_TRADE;
        }
        // 查询订单
        Order order = orderRepository.findById(Long.valueOf(payment.getOrderId())).orElse(null);
        if (order == null) {
            throw new YnceErrorException(YnceError.YNCE_204003);
        }
        UnionpayResponseVO unionpayResponseVO = umsPayService.tradeQuery(route, unionpaySn, (order.getConsignmentCompany() != null ? order.getConsignmentCompany().getId() : order.getSellerCompany().getId()));
        if (UnionpayAppTradeStatus.TRADE_SUCCESS.equals(unionpayResponseVO.getStatus())) {
            ThirdPartyPaySet thirdPartyPaySet = thirdPartyConfigUtil.getPlatform();
            if (thirdPartyPaySet == null) {
                throw new YnceErrorException("未配置第三方请求地址");
            }
            // 生成收款单以及后续业务操作
            OrderOnlinePayVO orderOnlinePayVO = new OrderOnlinePayVO();
            orderOnlinePayVO.setOrderId(Long.valueOf(payment.getOrderId()));
            orderOnlinePayVO.setPaymentId(payment.getId());
            orderOnlinePayVO.setPayTime(unionpayResponseVO.getPayTime());
            orderOnlinePayVO.setExternalId(payment.getExternalId());
            JSONObject result = HttpClientUtil.getInstance().sendPost(thirdPartyPaySet.getServiceUrl() + RouteUtil.ROUTE_RECEIPT_ONLINE_PAY, orderOnlinePayVO);
            if (!result.get("code").toString().equals("200")) {
                throw new YnceErrorException("线上收款失败！");
            }
            payment.setPayStatus(PayStatus.SUCC);
            payment.setSeqId(unionpayResponseVO.getSeqId());
            payment.setPaymentTime(unionpayResponseVO.getPayTime());
            paymentRepository.save(payment);
        }
        return unionpayResponseVO.getStatus();
    }

    @Override
    public String refund(IRefundDTO iRefundDTO) {
        Payment payment = paymentRepository.findFirstBySnOrderByIdDesc(iRefundDTO.getPaymentNo());
        if (payment == null) {
            throw new YnceErrorException(YnceError.YNCE_205007);
        }
        if (!payment.getPayStatus().equals(PayStatus.SUCC)) {
            throw new YnceErrorException(YnceError.YNCE_204095, "支付单未支付");
        }
        if (StringUtils.isBlank(payment.getOrderId())) {
            throw new YnceErrorException(YnceError.YNCE_204095, "订单号为空");
        }
        // 查询订单
        Order order = orderRepository.findById(Long.valueOf(payment.getOrderId())).orElse(null);
        if (order == null) {
            throw new YnceErrorException(YnceError.YNCE_204003);
        }
        // 银联退款单号
        String unionpayRefundSn;
        // 执行退款操作
        switch (payment.getPaymentMethod()) {
            case WECHAT:
            case ALIPAY:
            case CHINA_UNIONPAY_QUICK_PASS:
                unionpayRefundSn = umsPayService.refund(payment.getUnionpaySn(), iRefundDTO.getAmount(), (order.getConsignmentCompany() != null ? order.getConsignmentCompany().getId() : order.getSellerCompany().getId()));
                break;
            default:
                throw new YnceErrorException(YnceError.YNCE_204095, "不支持此支付方式退款");
        }
        return unionpayRefundSn;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String aggregateCallBack(String merOrderId) {
        this.orderQuery(merOrderId);
        return "SUCCESS";
    }

    @Override
    public UnionpayResponseVO refundQuery(String refundMerOrderId) {
        return umsPayService.tradeQuery(RouteUtil.ROUTE_UNIONPAY_NETPAY_REFUND_QUERY, refundMerOrderId, null);
    }

    @Override
    public UnionpayResponseVO orderClose(Long paymentId) {
        Payment payment = paymentRepository.findById(paymentId).orElseThrow(() -> new YnceErrorException("支付单不存在"));
        String closeRoute = RouteUtil.ROUTE_UNIONPAY_NETPAY_CLOSE;
        if (payment.getPaymentMethod().equals(PaymentMethod.ALIPAY)) {
            closeRoute = RouteUtil.ROUTE_UNIONPAY_NETPAY_TRADE_CLOSE;
        } else if (payment.getPaymentMethod().equals(PaymentMethod.WECHAT)) {
            closeRoute = RouteUtil.ROUTE_UNIONPAY_NETPAY_WX_CLOSE;
        }
        // 查询订单
        Order order = orderRepository.findById(Long.valueOf(payment.getOrderId())).orElse(null);
        if (order == null) {
            throw new YnceErrorException(YnceError.YNCE_204003);
        }
        return umsPayService.tradeClose(closeRoute, payment.getExternalId(), order.getConsignmentCompany() != null ? order.getConsignmentCompany().getId() : order.getSellerCompany().getId());
    }
}
