package com.jsowell.service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.huifu.adapay.core.AdapayCore;
import com.huifu.adapay.core.util.AdapaySign;
import com.jsowell.adapay.vo.PaymentInfo;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.core.domain.vo.AuthorizedDeptVO;
import com.jsowell.common.core.domain.ykc.RealTimeMonitorData;
import com.jsowell.common.core.domain.ykc.TransactionRecordsData;
import com.jsowell.common.core.page.PageResponse;
import com.jsowell.common.core.redis.RedisCache;
import com.jsowell.common.enums.AcquirerEnum;
import com.jsowell.common.enums.DelFlagEnum;
import com.jsowell.common.enums.InvoiceRecordEnum;
import com.jsowell.common.enums.MemberWalletEnum;
import com.jsowell.common.enums.adapay.AdapayEventEnum;
import com.jsowell.common.enums.adapay.AdapayPayChannelEnum;
import com.jsowell.common.enums.uniapp.OccupyOrderPayStatusEnum;
import com.jsowell.common.enums.uniapp.OccupyOrderStatusEnum;
import com.jsowell.common.enums.ykc.*;
import com.jsowell.common.exception.BusinessException;
import com.jsowell.common.util.DateUtils;
import com.jsowell.common.util.SecurityUtils;
import com.jsowell.common.util.StringUtils;
import com.jsowell.common.util.bean.BeanUtils;
import com.jsowell.pile.domain.*;
import com.jsowell.pile.dto.*;
import com.jsowell.pile.service.*;
import com.jsowell.pile.service.programlogic.AbstractProgramLogic;
import com.jsowell.pile.service.programlogic.ProgramLogicFactory;
import com.jsowell.pile.util.MerchantUtils;
import com.jsowell.pile.util.UserUtils;
import com.jsowell.pile.vo.base.*;
import com.jsowell.pile.vo.base.PileInfoVO;
import com.jsowell.pile.vo.uniapp.customer.*;
import com.jsowell.pile.vo.uniapp.customer.InvoiceRecordVO;
import com.jsowell.pile.vo.web.*;
import com.jsowell.thirdparty.common.CommonService;
import com.jsowell.wxpay.response.WechatPayNotifyParameter;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
public class OrderService {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private OrderBasicInfoService orderBasicInfoService;

    @Autowired
    private PileRemoteService pileRemoteService;

    @Autowired
    private PileService pileService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private MemberBasicInfoService memberBasicInfoService;

    @Autowired
    private OrderPayRecordService orderPayRecordService;

    @Autowired
    private WechatPayService wechatPayService;

    @Autowired
    private MemberTransactionRecordService memberTransactionRecordService;

    @Autowired
    private PileStationInfoService pileStationInfoService;

    @Autowired
    private OrderInvoiceRecordService orderInvoiceRecordService;

    @Autowired
    private PileStationWhitelistService pileStationWhitelistService;

    @Autowired
    private AdapayCallbackRecordService adapayCallbackRecordService;

    @Autowired
    private MemberInvoiceTitleService memberInvoiceTitleService;

    @Autowired
    private AdapayRefundRecordService adapayRefundRecordService;

    @Autowired
    private AdapayMemberAccountService adapayMemberAccountService;

    @Autowired
    private ClearingWithdrawInfoService clearingWithdrawInfoService;

    @Autowired
    private MemberAdapayRecordService memberAdapayRecordService;

    @Resource
    private OrderPileOccupyService orderPileOccupyService;

    @Resource
    private PileMerchantInfoService pileMerchantInfoService;

    @Resource
    private MemberWalletLogService memberWalletLogService;

    @Resource
    private ClearingBillInfoService clearingBillInfoService;

    @Autowired
    private ThirdPartyStationRelationService thirdPartyStationRelationService;

    @Autowired
    private IThirdpartySnRelationService snRelationService;

    @Autowired
    private CommonService commonService;

    @Resource
    private RedisCache redisCache;

    /**
     * 生成订单
     *
     * @param dto
     * @return
     */
    // @Deprecated
    // public String generateOrder(GenerateOrderDTO dto) throws ParseException {
    //     OrderBasicInfo basicInfo = orderBasicInfoService.generateOrder(dto);
    //     if (basicInfo != null) {
    //         return basicInfo.getOrderCode();
    //     }
    //     return null;
    // }

    /**
     * 生成订单
     *
     * @param dto
     * @return
     */
    public String generateOrderV2(GenerateOrderDTO dto) throws ParseException {
        String delayMode = null;
        if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.WX_LITE.getValue())) {
            delayMode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getAppId());
        } else if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.ALIPAY_LITE.getValue())) {
            delayMode = pileMerchantInfoService.getDelayModeByAlipayAppId(dto.getAppId());
        }
        // 新逻辑
        AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(delayMode);
        OrderBasicInfo orderBasicInfo = orderLogic.generateOrder(dto);
        if (orderBasicInfo != null) {
            return orderBasicInfo.getOrderCode();
        }
        return null;
    }

    /**
     * 订单支付
     *
     * @param dto
     */
    // @Deprecated
    // public Map<String, Object> payOrder(PayOrderDTO dto) throws Exception {
    //     return orderBasicInfoService.payOrder(dto);
    // }

    /**
     * 订单支付
     *
     * @param dto
     */
    public Map<String, Object> payOrderV2(PayOrderDTO dto) {
        // String mode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getWechatAppId());

        String delayMode = null;
        if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.WX_LITE.getValue())) {
            delayMode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getWechatAppId());
        } else if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.ALIPAY_LITE.getValue())) {
            delayMode = pileMerchantInfoService.getDelayModeByAlipayAppId(dto.getAlipayAppId());
        }
        dto.setDelayMode(delayMode);

        // 获取处理逻辑
        AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(delayMode);
        Map<String, Object> map = orderLogic.payOrder(dto);
        return map;
    }

    /**
     * 结算订单
     * endCharging
     *
     * @param dto 结算订单参数
     */
    public void settleOrderForWeb(SettleOrderDTO dto) {
        orderBasicInfoService.analysisPileParameter(dto);
        // 查询订单详情，验证订单中的桩编号是否正确
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode());
        if (orderBasicInfo == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL);
        }
        if (!(StringUtils.equals(orderBasicInfo.getPileSn(), dto.getPileSn())
                && StringUtils.equals(orderBasicInfo.getConnectorCode(), dto.getConnectorCode()))) {
            throw new BusinessException(ReturnCodeEnum.CODE_ORDER_PILE_MAPPING_ERROR);
        }
        // push远程停机指令
        pileRemoteService.remoteStopCharging(dto.getPileSn(), dto.getConnectorCode(), orderBasicInfo.getTransactionCode());

    }

    /**
     * 通过会员Id查询订单列表
     *
     * @param memberId 会员Id
     * @return 订单信息集合
     */
    public PageResponse getListByMemberIdAndOrderStatus(String memberId, UniAppQueryOrderDTO dto) throws ParseException {
        String orderStatus = dto.getOrderStatus();
        if (StringUtils.isBlank(orderStatus)) {
            throw new BusinessException(ReturnCodeEnum.CODE_PARAM_NOT_NULL_ERROR);
        }
        ArrayList<String> orderStatusList = Lists.newArrayList();
        if (StringUtils.equals("2", orderStatus)) {
            // 查未完成订单
            CollectionUtils.addAll(orderStatusList, "0", "1", "2", "3", "4", "5");
        } else if (StringUtils.equals("3", orderStatus)) {
            // 查已完成订单
            orderStatusList.add("6");
        } else if (StringUtils.equals("4", orderStatus)) {
            // 查询正在进行中的订单
            orderStatusList.add("1");
        }
        // 分页
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        List<OrderVO> list = orderBasicInfoService.getListByMemberIdAndOrderStatus(memberId, orderStatusList);

        PageInfo<OrderVO> pageInfo = new PageInfo<>(list);

        for (OrderVO orderVO : pageInfo.getList()) {
            orderVO.setPileConnectorCode(orderVO.getPileSn() + orderVO.getConnectorCode());
            // 从缓存中获取充电时长
            List<RealTimeMonitorData> chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderVO.getTransactionCode());
            // 默认时间倒序排列，因此只取第一条就可以
            if (CollectionUtils.isEmpty(chargingRealTimeData)) {
                orderVO.setChargingTime("-");
                continue;
            }
            RealTimeMonitorData realTimeMonitorData = chargingRealTimeData.get(0);
            String sumChargingTime = realTimeMonitorData.getSumChargingTime(); // xx分钟
            String chargingTime = "-";
            try {
                // 分钟转成 x时x分
                chargingTime = DateUtils.convertMinutesToTime(Integer.parseInt(sumChargingTime));
            } catch (Exception e) {
                orderVO.setChargingTime(sumChargingTime);
                continue;
            }
            // String chargingTime = "0分钟";
            // if (orderVO.getStartTime() != null) {
            //     Date startTimeDate = DateUtils.parseDate(orderVO.getStartTime());
            //     Date endTimeDate;
            //     if (orderVO.getEndTime() != null) {
            //         endTimeDate = DateUtils.parseDate(orderVO.getEndTime());
            //         // 计算出两个时间差
            //         chargingTime = DateUtils.getDatePoor(endTimeDate, startTimeDate);
            //     } else {
            //         endTimeDate = new Date();
            //     }
            //
            // }
            orderVO.setChargingTime(chargingTime);
        }

        // 返回结果集
        PageResponse pageResponse = PageResponse.builder()
                .pageNum(dto.getPageNum())
                .pageSize(dto.getPageSize())
                .list(pageInfo.getList())
                .pages(pageInfo.getPages())
                .total(pageInfo.getTotal())
                .build();
        return pageResponse;
    }

    /**
     * 微信支付v3
     *
     * @param dto
     * @return
     * @throws Exception
     */
    public Map<String, Object> weixinPayV3(WeixinPayDTO dto) throws Exception {
        return wechatPayService.weixinPayV3(dto);
    }

    /**
     * 用户停止充电
     *
     * @param dto
     */
    public void stopCharging(StopChargingDTO dto) {
        // 查订单
        OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode());
        if (orderInfo == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL);
        }
        // 判断订单状态是不是已经结算了
        if (StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) {
            throw new BusinessException(ReturnCodeEnum.CODE_ORDER_COMPLETE_ERROR);
        }
        // 校验订单中的会员与操作会员是否一致
        if (!StringUtils.equals(orderInfo.getMemberId(), dto.getMemberId())) {
            throw new BusinessException(ReturnCodeEnum.CODE_ORDER_MEMBER_NOT_MATCH_ERROR);
        }
        // 判断该桩是否推送了第三方站点（需要我方平台发送启动指令的，如：华为平台）
        List<ThirdPartySnRelationVO> list = snRelationService.selectSnRelationListByParams(orderInfo.getStationId(), orderInfo.getPileSn(), null);
        if (CollectionUtils.isNotEmpty(list)) {
            for (ThirdPartySnRelationVO vo : list) {
                ThirdPartyCommonStopChargeDTO commonStopChargeDTO = new ThirdPartyCommonStopChargeDTO();
                commonStopChargeDTO.setThirdPartyType(vo.getThirdPartyType());
                commonStopChargeDTO.setOrderBasicInfo(orderInfo);
                // 调用统一停止充电接口
                String result = commonService.commonStopCharge(commonStopChargeDTO);
                log.info("订单:{} 调用统一停止充电接口, result:{}", orderInfo, result);
            }
        }else {
            // 发送停止指令
            pileRemoteService.remoteStopCharging(orderInfo.getPileSn(), orderInfo.getConnectorCode(), orderInfo.getTransactionCode());
        }

        // List<ThirdPartyStationRelationVO> relationInfoList = thirdPartyStationRelationService.getRelationInfoList(orderInfo.getStationId());
        //
        // if (CollectionUtils.isNotEmpty(relationInfoList)) {
        //     for (ThirdPartyStationRelationVO vo : relationInfoList) {
        //         String startMode = vo.getStartMode();
        //         if (StringUtils.equals(Constants.ONE, startMode)) {
        //             // 启动类型为 1 的即为对接了类似华为平台，需要调用第三方平台的统一停止充电接口
        //             ThirdPartyCommonStopChargeDTO commonStopChargeDTO = new ThirdPartyCommonStopChargeDTO();
        //             commonStopChargeDTO.setThirdPartyType(vo.getThirdPartyType());
        //             commonStopChargeDTO.setOrderBasicInfo(orderInfo);
        //             // 调用统一停止充电接口
        //             String result = commonService.commonStopCharge(commonStopChargeDTO);
        //             log.info("订单:{}调用第三方平台统一停止充电接口，调用结果 SuccStat:{}", orderInfo.getOrderCode(), result);
        //         }else {
        //             // 发送停止指令
        //             pileRemoteService.remoteStopCharging(orderInfo.getPileSn(), orderInfo.getConnectorCode(), orderInfo.getTransactionCode());
        //         }
        //     }
        // }else {
        //     // 发送停止指令
        //     pileRemoteService.remoteStopCharging(orderInfo.getPileSn(), orderInfo.getConnectorCode(), orderInfo.getTransactionCode());
        // }
        // 发送停止指令
        // pileRemoteService.remoteStopCharging(orderInfo.getPileSn(), orderInfo.getConnectorCode(), orderInfo.getTransactionCode());
        log.info("用户停止充电, orderCode:{}, transactionCode:{}, 发送停机指令成功", dto.getOrderCode(), orderInfo.getTransactionCode());
    }

    /**
     * 微信退款
     *
     * @param dto
     */
    public void weChatRefund(ApplyRefundDTO dto) {
        log.info("微信退款接口 param:{}", JSON.toJSONString(dto));
        orderBasicInfoService.weChatRefund(dto);
    }

    /**
     * 汇付退款
     *
     * @param dto
     */
    public void adapayRefund(ApplyRefundDTO dto) {
        log.info("汇付退款 param:{}", JSON.toJSONString(dto));
        // 退款有两种情况 1-订单结算退款  2-用户余额退款
        String refundType = dto.getRefundType();
        if (StringUtils.equals(refundType, "1")) {
            orderBasicInfoService.refundOrderWithAdapay(dto);
        } else if (StringUtils.equals(refundType, "2")) {
            orderBasicInfoService.refundBalanceWithAdapay(dto);
        } else {
            log.warn("没有找到退款处理逻辑");
        }
    }

    /**
     * 查询订单详情信息
     *
     * @param orderCode 订单编号
     * @return
     */
    public OrderDetailInfoVO queryOrderDetailInfo(String orderCode) {
        OrderDetailInfoVO vo = new OrderDetailInfoVO();

        // 订单信息
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
        if (orderBasicInfo == null) {
            return vo;
        }
        OrderDetailInfoVO.OrderInfo order = new OrderDetailInfoVO.OrderInfo();
        order.setOrderCode(orderBasicInfo.getOrderCode());
        order.setTransactionCode(orderBasicInfo.getTransactionCode());
        order.setOrderStatus(orderBasicInfo.getOrderStatus());
        order.setLogicCard(orderBasicInfo.getLogicCard());
        String describe = orderBasicInfoService.transformOrderStatusDescribe(orderBasicInfo.getOrderStatus(), orderBasicInfo.getPayStatus());
        order.setOrderStatusDescribe(describe);
        order.setStartTime(DateUtils.formatDateTime(orderBasicInfo.getChargeStartTime()));
        order.setEndTime(DateUtils.formatDateTime(orderBasicInfo.getChargeEndTime()));
        order.setCreateTime(DateUtils.formatDateTime(orderBasicInfo.getCreateTime()));
        order.setStopReasonMsg(orderBasicInfo.getReason());
        order.setStartSOC(orderBasicInfo.getStartSoc());
        order.setEndSOC(orderBasicInfo.getEndSoc());
        order.setDiscountAmount(String.valueOf(orderBasicInfo.getDiscountAmount()));
        order.setSettleAmount(String.valueOf(orderBasicInfo.getSettleAmount()));
        order.setSettlementTime(DateUtils.formatDateTime(orderBasicInfo.getSettlementTime()));
        vo.setOrderInfo(order);

        // 设备信息
        PileInfoVO pileInfoVO = pileService.selectPileInfoBySn(orderBasicInfo.getPileSn());
        vo.setPileInfo(pileInfoVO);

        // 枪口实时数据信息
        String pileConnectorCode = orderBasicInfo.getPileSn() + orderBasicInfo.getConnectorCode();
        QueryConnectorListDTO dto = new QueryConnectorListDTO();
        dto.setConnectorCodeList(Lists.newArrayList(pileConnectorCode));
        List<RealTimeMonitorData> chargingRealTimeDataList = orderBasicInfoService.getChargingRealTimeData(orderBasicInfo.getTransactionCode());
        if (CollectionUtils.isNotEmpty(chargingRealTimeDataList)) {
            List<OrderDetailInfoVO.PileMonitorData> infoList = Lists.newArrayList();
            for (RealTimeMonitorData realTimeMonitorData : chargingRealTimeDataList) {
                OrderDetailInfoVO.PileMonitorData info = new OrderDetailInfoVO.PileMonitorData();
                info.setInstantCurrent(realTimeMonitorData.getOutputCurrent()); // 电流
                info.setInstantVoltage(realTimeMonitorData.getOutputVoltage()); // 电压
                info.setInstantPower(realTimeMonitorData.getOutputPower());  // 功率
                info.setSOC(realTimeMonitorData.getSOC());
                info.setTime(realTimeMonitorData.getDateTime());  // 时间
                infoList.add(info);
            }

            // 监控信息
            OrderDetailInfoVO.OrderRealTimeInfo realTimeInfo = new OrderDetailInfoVO.OrderRealTimeInfo();
            RealTimeMonitorData realTimeMonitorData = chargingRealTimeDataList.get(0); // 最后一次实时数据
            realTimeInfo.setOrderAmount(realTimeMonitorData.getChargingAmount());
            realTimeInfo.setChargedDegree(realTimeMonitorData.getChargingDegree());
            realTimeInfo.setChargingTime(realTimeMonitorData.getSumChargingTime());
            realTimeInfo.setTime(realTimeMonitorData.getDateTime());
            vo.setOrderRealTimeInfo(realTimeInfo);

            // 根据时间进行正序排序
            infoList = infoList.stream()
                    .sorted(Comparator.comparing(OrderDetailInfoVO.PileMonitorData::getTime))
                    .collect(Collectors.toList());
            vo.setRealTimeMonitorDataList(infoList);

            // 最后一次实时数据
            vo.setLastMonitorData(realTimeMonitorData);
        }

        // 支付流水
        List<OrderDetailInfoVO.PayRecord> payRecords = orderPayRecordService.selectOrderPayInfoList(orderCode);
        vo.setPayRecordList(payRecords);

        // 查询退款明细
        List<OrderDetailInfoVO.OrderRefundInfo> orderRefundInfoList = orderBasicInfoService.getOrderRefundInfoList(orderBasicInfo);
        vo.setOrderRefundInfoList(orderRefundInfoList);

        // 查订单明细
        OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode);
        if (orderDetail != null) {
            OrderAmountDetailVO billingDetails = new OrderAmountDetailVO();
            BeanUtils.copyBeanProp(billingDetails, orderDetail);
            vo.setBillingDetails(billingDetails);

            List<OrderPeriodAmountVO> orderPeriodAmountVOS = orderBasicInfoService.transformPeriodAmountByOrderDetail(orderDetail);
            vo.setChargeDetails(orderPeriodAmountVOS);
        }

        // 用户信息
        MemberVO memberVO = memberService.getMemberInfoByMemberId(orderBasicInfo.getMemberId());
        vo.setMemberInfo(memberVO);

        try {
            // 因为原来的数据在redis中是永久保存，所以这里做下查询详情的时候，发现已经是完成的订单，redis数据存到表中
            if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) {
                // 如果是已完成的订单，把redis中的实时数据存到表中
                orderBasicInfoService.realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderBasicInfo.getOrderCode());
            }
        } catch (Exception e) {
            log.error("后管查询订单详情时把redis中的实时数据存到表发生异常", e);
        }

        try {
            if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.IN_THE_CHARGING.getValue())) {
                RealTimeMonitorData lastMonitorData = vo.getLastMonitorData();
                if (lastMonitorData == null || DateUtils.intervalTime(lastMonitorData.getDateTime(), DateUtils.getDateTime()) > 2L) {
                    // 没有实时数据 或者 间隔时间超过2分钟, 订单状态修改为异常
                    orderBasicInfo.setOrderStatus(OrderStatusEnum.ABNORMAL.getValue());
                    orderBasicInfo.setReason("充电桩长时间没有上传实时数据");
                    orderBasicInfoService.updateOrderBasicInfo(orderBasicInfo);
                }
            }
        } catch (Exception e) {
            log.error("后管查询订单详情时校验订单状态", e);
        }
        return vo;
    }

    /**
     * 微信支付退款回调
     *
     * @param request
     * @param body
     * @throws Exception
     */
    public void wechatPayRefundCallback(HttpServletRequest request, WechatPayNotifyParameter body) throws Exception {
        // 获取微信退款成功返回的信息
        Map<String, Object> map = wechatPayService.wechatPayRefundCallbackInfo(request, body);
    }

    /**
     * 获取小程序订单详情
     *
     * @param orderCode
     * @return
     */
    public UniAppOrderVO getUniAppOrderDetail(String orderCode) {
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
        OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode);
        UniAppOrderVO vo = new UniAppOrderVO();
        if (orderBasicInfo == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL);
        }

        String pileSn = orderBasicInfo.getPileSn();
        String connectorCode = orderBasicInfo.getConnectorCode();

        // 异步发送获取实时数据指令
        if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.IN_THE_CHARGING.getValue())) {
            CompletableFuture.runAsync(() -> {
                try {
                    pileRemoteService.getRealTimeMonitorData(pileSn, connectorCode);
                } catch (Exception e) {
                    log.error("异步发送获取实时数据指令error", e);
                }
            });
        }

        vo.setOrderCode(orderBasicInfo.getOrderCode());
        vo.setPileSn(pileSn);
        vo.setConnectorCode(connectorCode);
        vo.setPileConnectorCode(pileSn + connectorCode);
        String orderStatus = orderBasicInfo.getOrderStatus();
        vo.setOrderStatus(orderStatus);
        // 订单状态描述
        String orderStatusDescribe = orderBasicInfoService.transformOrderStatusDescribe(orderStatus, orderBasicInfo.getPayStatus());
        vo.setOrderStatusDescribe(orderStatusDescribe);
        if (Objects.nonNull(orderBasicInfo.getChargeStartTime())) {
            vo.setStartChargingTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderBasicInfo.getChargeStartTime()));
        }
        Date chargeEndTime = orderBasicInfo.getChargeEndTime();
        if (Objects.nonNull(chargeEndTime)) {
            vo.setEndChargingTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, chargeEndTime));
        }
        PileStationVO stationInfo = pileStationInfoService.getStationInfo(orderBasicInfo.getStationId());
        vo.setStationName(stationInfo.getStationName());
        vo.setReason(orderBasicInfo.getReason());
        vo.setOrderAmount(String.valueOf(orderBasicInfo.getOrderAmount()));
        vo.setPayAmount(String.valueOf(orderBasicInfo.getPayAmount()));
        vo.setPayMode(orderBasicInfo.getPayMode());
        vo.setRemedialAmount(String.valueOf(orderBasicInfo.getRemedialAmount()));
        if (StringUtils.isNotBlank(String.valueOf(stationInfo.getFreeTime()))) {
            vo.setFreeTime(stationInfo.getFreeTime());
        }
        if (StringUtils.isNotBlank(String.valueOf(stationInfo.getOccupyFee()))) {
            vo.setOccupyFee(stationInfo.getOccupyFee());
        }

        // 获取充电桩枪口信息
        PileConnectorDetailVO pileConnectorDetailVO = pileService.queryPileConnectorDetail(vo.getPileConnectorCode());
        if (pileConnectorDetailVO != null) {
            vo.setPileConnectorStatus(pileConnectorDetailVO.getConnectorStatus());
        }

        // 优惠金额
        vo.setDiscountAmount(String.valueOf(orderBasicInfo.getDiscountAmount()));
        // 实付金额
        vo.setActualAmount(String.valueOf(orderBasicInfo.getOrderAmount().subtract(orderBasicInfo.getDiscountAmount())));

        // 获取订单充电数据
        List<RealTimeMonitorData> monitorDataList = orderBasicInfoService.getChargingRealTimeData(orderBasicInfo.getTransactionCode());
        if (CollectionUtils.isNotEmpty(monitorDataList)) {
            List<UniAppOrderVO.ChargingData> chargingDataList = Lists.newArrayList();
            UniAppOrderVO.ChargingData data = null;
            for (int i = 0; i < monitorDataList.size(); i++) {
                RealTimeMonitorData monitorData = monitorDataList.get(i);
                data = new UniAppOrderVO.ChargingData();
                data.setDateTime(monitorData.getDateTime());
                String outputVoltage = monitorData.getOutputVoltage();
                data.setOutputVoltage(outputVoltage);
                String outputCurrent = monitorData.getOutputCurrent();
                data.setOutputCurrent(outputCurrent);
                BigDecimal power = new BigDecimal(outputCurrent).multiply(new BigDecimal(outputVoltage))
                        .divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);
                data.setPower(power.toString());
                data.setSOC(monitorData.getSOC());
                data.setBatteryMaxTemperature(monitorData.getBatteryMaxTemperature());
                chargingDataList.add(data);
                // vo中的实时数据，最新一条就取monitorDataList第一个
                if (i == 0) {
                    vo.setBatteryMaxTemperature(data.getBatteryMaxTemperature());
                    vo.setOutputPower(data.getPower());
                    vo.setOutputCurrent(data.getOutputCurrent());
                    vo.setOutputVoltage(data.getOutputVoltage());
                    vo.setSOC(data.getSOC());
                    BigDecimal chargingAmount = new BigDecimal(monitorData.getChargingAmount()).setScale(4, RoundingMode.HALF_UP); // 充电金额
                    vo.setChargingAmount(chargingAmount.toString());
                    BigDecimal chargingDegree = new BigDecimal(monitorData.getChargingDegree()).setScale(4, RoundingMode.HALF_UP); // 充电度数
                    vo.setChargingDegree(chargingDegree.toString());
                    vo.setSumChargingTime(monitorData.getSumChargingTime());
                    vo.setTimeRemaining(monitorData.getTimeRemaining());
                }
            }
            // monitorDataList是按照时间倒序的，chargingDataList需要按照时间正序
            Collections.reverse(chargingDataList);
            vo.setChargingDataList(chargingDataList);
        }
        if (orderDetail != null) {
            OrderAmountDetailVO billingDetails = new OrderAmountDetailVO();
            BeanUtils.copyBeanProp(billingDetails, orderDetail);
            vo.setBillingDetails(billingDetails);
            if (StringUtils.equals(OrderStatusEnum.ORDER_COMPLETE.getValue(), orderStatus)) {
                BigDecimal totalUsedElectricity = orderDetail.getTotalUsedElectricity();
                if (totalUsedElectricity != null && StringUtils.isNotBlank(vo.getChargingAmount())
                        && totalUsedElectricity.compareTo(new BigDecimal(vo.getChargingAmount())) > 0) {
                    vo.setChargingDegree(String.valueOf(totalUsedElectricity));
                }
            }
        }

        try {
            // 因为原来的数据在redis中是永久保存，所以这里做下查询详情的时候，发现已经是完成的订单，redis数据存到表中
            if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) {
                // 如果是已完成的订单，把redis中的实时数据存到表中
                orderBasicInfoService.realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderBasicInfo.getOrderCode());
            }
        } catch (Exception e) {
            log.error("后管查询订单详情时把redis中的实时数据存到表发生异常", e);
        }
        return vo;
    }

    /**
     * 小程序订单详情V2
     *
     * @param orderCode
     * @return
     */
    public UniAppOrderDetailVO getUniAppOrderDetailV2(String orderCode) {
        UniAppOrderDetailVO resultVO = new UniAppOrderDetailVO();


        return resultVO;
    }

    /**
     * 根据订单号查询充电桩启动状态
     *
     * @param orderCode 订单编号
     * @return 0: 未启动，1: 启动成功，2: 启动失败
     */
    public Map<String, String> selectPileStarterStatus(String orderCode) {
        OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
        if (orderInfo == null) {
            throw new BusinessException(ReturnCodeEnum.CODE_QUERY_ORDER_INFO_IS_NULL);
        }
        String status = Constants.ZERO;
        String reason = null;

        // 如果是订单完成状态
        if (StringUtils.equals(orderInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) {
            status = Constants.TWO;
            reason = orderInfo.getReason();
        } else {
            // 查询订单的实时监测数据
            List<RealTimeMonitorData> chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderInfo.getTransactionCode());
            if (CollectionUtils.isNotEmpty(chargingRealTimeData)) {
                // 实时监测数据不为空说明已经在充电中了
                status = Constants.ONE;
            }
        }

        Map<String, String> resultMap = Maps.newHashMap();
        resultMap.put("status", status);
        resultMap.put("reason", reason);
        resultMap.put("orderCode", orderInfo.getOrderCode());
        resultMap.put("pileConnectorCode", orderInfo.getPileConnectorCode());
        return resultMap;
    }

    /**
     * 关闭支付未启动的订单
     *
     * @param dto
     */
    public void closeStartFailedOrder(QueryOrderDTO dto) {
        orderBasicInfoService.closeStartFailedOrder(dto.getStartTime(), dto.getEndTime());
    }

    /**
     * 人工结算订单
     *
     * @param dto
     */
    public boolean manualSettlementOrder(ManualSettlementDTO dto) {
        log.info("人工结算订单-begin orderCode:{}", dto.getOrderCode());
        // 查询订单
        OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getOrderCode());
        if (orderBasicInfo == null) {
            log.info("人工结算订单-根据订单号:{}, 查询为null", dto.getOrderCode());
            return false;
        }
        // 当前登录用户，是否可以结算该订单
        AuthorizedDeptVO authorizedMap = UserUtils.getAuthorizedMap();
        if (authorizedMap == null) {
            log.info("人工结算订单-当前登录管理员无权限");
            return false;
        }

        List<String> stationDeptIds = authorizedMap.getStationDeptIds();
        if (CollectionUtils.isEmpty(stationDeptIds)) {
            // 运营商管理员
            List<String> merchantDeptIds = authorizedMap.getMerchantDeptIds();
        }

        // 充电金额
        String chargingAmount = dto.getChargingAmount();
        // 充电度数
        String chargingDegree = dto.getChargingDegree();
        if (StringUtils.equals(chargingAmount, Constants.ZERO) || StringUtils.equals(chargingDegree, Constants.ZERO)) {
            // 获取最后一次实时数据
            List<RealTimeMonitorData> chargingRealTimeData = orderBasicInfoService.getChargingRealTimeData(orderBasicInfo.getTransactionCode());
            if (CollectionUtils.isNotEmpty(chargingRealTimeData)) {
                RealTimeMonitorData realTimeMonitorData = chargingRealTimeData.get(0);
                chargingAmount = realTimeMonitorData.getChargingAmount();
                chargingDegree = realTimeMonitorData.getChargingDegree();
            }
        }

        // 查询订单退款记录，如存在退款说明已经结算过，不能再次结算
        List<OrderDetailInfoVO.OrderRefundInfo> orderRefundInfoList = orderBasicInfoService.getOrderRefundInfoList(orderBasicInfo);
        if (CollectionUtils.isNotEmpty(orderRefundInfoList)) {
            // 已退款金额
            BigDecimal refunded = orderRefundInfoList.stream()
                    .map(x -> Objects.nonNull(x.getReverseAmt()) ? new BigDecimal(x.getReverseAmt()) : BigDecimal.ZERO)
                    .reduce(BigDecimal.ZERO,BigDecimal::add);
            if (Objects.nonNull(orderBasicInfo.getPayAmount())) {
                chargingAmount = orderBasicInfo.getPayAmount().subtract(refunded).toString();
                log.info("订单:{}, 已经存在退款记录:{}, 支付金额{}, 退款金额:{}, 重新计算消费金额为:{}",
                        orderBasicInfo.getOrderCode(), JSON.toJSONString(orderRefundInfoList), orderBasicInfo.getPayAmount(), refunded, chargingAmount);
            }
        }

        // 组装交易记录数据
        TransactionRecordsData data = new TransactionRecordsData();
        data.setConsumptionAmount(chargingAmount); // 总消费金额
        data.setTotalElectricity(chargingDegree); // 总用电量
        data.setStopReasonMsg("人工结算订单，操作人:" + SecurityUtils.getUsername()); // 停止原因

        // 结算订单 新逻辑
        String mode = pileMerchantInfoService.getDelayModeByMerchantId(orderBasicInfo.getMerchantId());
        AbstractProgramLogic orderLogic = ProgramLogicFactory.getProgramLogic(mode);
        orderLogic.settleOrder(data, orderBasicInfo);

        // 发送停止充电指令
        pileRemoteService.remoteStopCharging(orderBasicInfo.getPileSn(), orderBasicInfo.getConnectorCode(), orderBasicInfo.getTransactionCode());

        log.info("人工结算订单-end orderCode:{}", dto.getOrderCode());

        // 异步推送第三方平台订单信息
        CompletableFuture.runAsync(() -> {
            try {
                commonService.commonPushOrderInfo(orderBasicInfo);
            } catch (Exception e) {
                log.error("人工结算订单 推送第三方平台订单信息error, orderCode:{}", orderBasicInfo.getOrderCode(), e);
            }
        });
        return true;
    }

    /**
     * 当前登录会员 获取支付方式
     *
     * @param dto
     */
    public List<PayModeVO> getPayMode(GetPayModeDTO dto) {
        log.info("当前登录会员 获取支付方式, param:{}, 请求来源:{}", JSON.toJSONString(dto), dto.getRequestSource());
        List<PayModeVO> result = Lists.newArrayList();
        // 查询会员在站点是否是白名单用户
        PileStationWhitelist whitelist = pileStationWhitelistService.queryWhitelistByMemberId(dto.getStationId(), dto.getMemberId());

        // 查询是否为平台测试员
        PlatformTesterVO platformTesterVO = memberBasicInfoService.selectPlatformTesterStatus(dto.getMemberId());

        // 根据memberId查询该用户是否是希晓的会员
        MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMemberId(dto.getMemberId());

        boolean flag = whitelist != null || StringUtils.equals(platformTesterVO.getStatus(), Constants.ONE);

        if (flag) {
            result.add(
                    PayModeVO.builder()
                            .payModeCode(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue())
                            .payModeName(OrderPayModeEnum.PAYMENT_OF_WHITELIST.getLabel())
                            .build()
            );
        } else {
            // 微信支付
            if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.WX_LITE.getValue())) {
                result.add(
                        PayModeVO.builder()
                                .payModeCode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())
                                .payModeName(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getLabel())
                                .build()
                );
            }
            // 支付宝支付
            if (StringUtils.equals(dto.getRequestSource(), AdapayPayChannelEnum.ALIPAY_LITE.getValue())) {
                result.add(
                        PayModeVO.builder()
                                .payModeCode(OrderPayModeEnum.PAYMENT_OF_ALIPAY.getValue())
                                .payModeName(OrderPayModeEnum.PAYMENT_OF_ALIPAY.getLabel())
                                .build()
                );
            }
            // 如果是希晓的会员，将余额支付添加进去
            if (MerchantUtils.isXiXiaoMerchant(String.valueOf(memberBasicInfo.getMerchantId()))) { // 35-希晓
                // 余额支付
                result.add(
                        PayModeVO.builder()
                                .payModeCode(OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())
                                .payModeName(OrderPayModeEnum.PAYMENT_OF_BALANCE.getLabel())
                                .build()
                );
            }
        }
        return result;
    }

    /**
     * 查询未开发票订单
     * 时间限制15天内
     *
     * @param dto
     * @return
     */
    public List<OrderVO> queryUninvoicedOrderList(QueryOrderDTO dto) {
        int i = 15;

        // 查询最近15天完成的订单
        LocalDateTime dateTime = LocalDateTime.now().plusDays(-i);
        List<OrderVO> orderList = orderBasicInfoService.getListByMemberIdAndOrderStatus(dto.getMemberId(), Lists.newArrayList("6"), dateTime);

        // 过滤掉订单金额为0的
        orderList = orderList.stream()
                .filter(x -> x.getSettleAmount().compareTo(BigDecimal.ZERO) > 0)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(orderList)) {
            return orderList;
        }

        // 查询最近60天申请开票记录
        QueryInvoiceRecordDTO build = QueryInvoiceRecordDTO.builder()
                .memberId(dto.getMemberId())
                .startTime(dateTime)
                .build();
        List<OrderInvoiceRecord> orderInvoiceRecords = orderInvoiceRecordService.selectInvoiceRecordList(build);
        if (CollectionUtils.isEmpty(orderInvoiceRecords)) {
            return orderList;
        }

        // 排除掉已经申请过的订单
        List<String> orderCodeList = orderInvoiceRecords.stream() // 转化为 Stream
                .map(OrderInvoiceRecord::getOrderCodes) // 获取 OrderInvoiceRecord 中的 orderCodes 字符串
                .flatMap(str -> Arrays.stream(str.split(Constants.DEFAULT_DELIMITER))) // 分隔逗号并转化为 Stream
                .collect(Collectors.toList()); // 收集为 List<String>

        orderList = orderList.stream()
                .filter(x -> !orderCodeList.contains(x.getOrderCode()))
                .collect(Collectors.toList());

        return orderList;
    }

    public List<StationInfoVO> queryUninvoicedStationList(QueryOrderDTO dto) {
        return Lists.newArrayList();
    }

    /**
     * 申请开票
     *
     * @param dto
     */
    public void applyOrderInvoice(ApplyOrderInvoiceDTO dto) {
        int i = 15;
        // 查询最近15天完成的订单
        LocalDateTime dateTime = LocalDateTime.now().plusDays(-i);
        // 查询最近15天 会员的开票记录
        List<OrderInvoiceRecord> orderInvoiceRecords = orderInvoiceRecordService.selectInvoiceRecordList(dto.getMemberId(), dateTime, LocalDateTime.now());
        List<String> orderCodeList = orderInvoiceRecords.stream() // 转化为 Stream
                .map(OrderInvoiceRecord::getOrderCodes) // 获取 OrderInvoiceRecord 中的 orderCodes 字符串
                .flatMap(str -> Arrays.stream(str.split(Constants.DEFAULT_DELIMITER))) // 分隔逗号并转化为 Stream
                .collect(Collectors.toList()); // 收集为 List<String>

        // 取交集 校验订单是否已经开票
        Set<String> intersection = Sets.intersection(Sets.newHashSet(orderCodeList), Sets.newHashSet(dto.getOrderCodes()));
        if (CollectionUtils.isNotEmpty(intersection)) {
            log.info("申请开票前端传的:{}订单号list, 包含已经申请的订单:{}", dto.getOrderCodes(), intersection);
            return;
        }

        // 查抬头信息
        MemberInvoiceTitle invoiceTitle = memberInvoiceTitleService.selectMemberInvoiceTitleById(Long.parseLong(dto.getTitleId()));

        if (StringUtils.isNotEmpty(dto.getReception())) {
            boolean b = false;
            if (StringUtils.isEmail(dto.getReception()) && !StringUtils.equals(dto.getReception(), invoiceTitle.getEmail())) {
                invoiceTitle.setEmail(dto.getReception());
                b = true;
            }
            if (StringUtils.isPhoneNumber(dto.getReception()) && !StringUtils.equals(dto.getReception(), invoiceTitle.getPhoneNumber())) {
                invoiceTitle.setPhoneNumber(dto.getReception());
                b = true;
            }
            if (b) {
                memberInvoiceTitleService.updateMemberInvoiceTitle(invoiceTitle);
            }
        }

        // 整理数据
        List<OrderVO> orderVOList = orderBasicInfoService.getListByOrderCodes(dto.getOrderCodes());

        // 根据运营商分组
        Map<String, List<OrderVO>> map = orderVOList.stream().collect(Collectors.groupingBy(OrderVO::getMerchantId));

        BigDecimal totalAmount = null;
        BigDecimal totalElecAmount = null;
        BigDecimal totalServiceAmount = null;
        // 根据运营商创建多笔开票记录
        for (Map.Entry<String, List<OrderVO>> entry : map.entrySet()) {
            totalAmount = BigDecimal.ZERO;
            totalElecAmount = BigDecimal.ZERO;
            totalServiceAmount = BigDecimal.ZERO;
            List<OrderVO> orders = entry.getValue();
            for (OrderVO orderVO : orders) {
                totalAmount = totalAmount.add(orderVO.getOrderAmount());
                totalElecAmount = totalElecAmount.add(orderVO.getTotalElectricityAmount());
                totalServiceAmount = totalServiceAmount.add(orderVO.getTotalServiceAmount());
            }

            // 入库
            OrderInvoiceRecord orderInvoiceRecord = new OrderInvoiceRecord();
            orderInvoiceRecord.setStatus(Constants.ZERO);
            orderInvoiceRecord.setMemberId(dto.getMemberId());
            orderInvoiceRecord.setMerchantId(entry.getKey());
            orderInvoiceRecord.setTitleId(dto.getTitleId());
            orderInvoiceRecord.setOrderCodes(String.join(Constants.DEFAULT_DELIMITER, dto.getOrderCodes()));
            orderInvoiceRecord.setTotalAmount(totalAmount);
            orderInvoiceRecord.setTotalElecAmount(totalElecAmount);
            orderInvoiceRecord.setTotalServiceAmount(totalServiceAmount);
            orderInvoiceRecordService.insertOrderInvoiceRecord(orderInvoiceRecord);
        }
    }

    /**
     * 查询开票记录
     *
     * @param dto
     * @return
     */
    public PageResponse queryInvoiceRecord(QueryInvoiceRecordDTO dto) {
        QueryInvoiceRecordDTO build = QueryInvoiceRecordDTO.builder()
                .memberId(dto.getMemberId())
                .build();
        int pageNo = dto.getPageNo() == null ? 1 : dto.getPageNo();
        int pageSize = dto.getPageSize() == null ? 10 : dto.getPageSize();
        PageHelper.startPage(pageNo, pageSize);
        // List<OrderInvoiceRecord> orderInvoiceRecords = orderInvoiceRecordService.selectInvoiceRecordList(build);
        List<OrderInvoiceRecordVO> orderInvoiceRecords = orderInvoiceRecordService.selectInvoiceVOList(build);
        PageInfo<OrderInvoiceRecordVO> pageInfo = new PageInfo<>(orderInvoiceRecords);
        List<InvoiceRecordVO> volist = Lists.newArrayList();
        for (OrderInvoiceRecordVO vo : orderInvoiceRecords) {
            volist.add(
                    InvoiceRecordVO.builder()
                            .status(InvoiceRecordEnum.getLabel(vo.getStatus()))
                            .totalAmount(vo.getTotalAmount())
                            .totalElecAmount(vo.getTotalElecAmount())
                            .totalServiceAmount(vo.getTotalServiceAmount())
                            .merchantName(vo.getMerchantName())
                            .merchantTel(vo.getMerchantTel())
                            .createTime(vo.getCreateTime())
                            .build()
            );
        }
        return PageResponse.builder()
                .total(pageInfo.getTotal())
                .pages(pageInfo.getPages())
                .pageNum(pageInfo.getPageNum())
                .pageSize(pageInfo.getPageSize())
                .list(volist)
                .build();
    }

    /**
     * 汇付支付 支付回调
     *
     * @param request
     * @throws Exception
     */
    public void adapayCallback(HttpServletRequest request) throws Exception {
        // 验签请参data
        String data = request.getParameter("data");
        // 验签请参sign
        String sign = request.getParameter("sign");

        // 验签请参publicKey
        String publicKey = AdapayCore.PUBLIC_KEY;
        log.info("汇付支付回调验签请参data={}, sign={}", data, sign);
        // 验签标记
        boolean checkSign = AdapaySign.verifySign(data, sign, publicKey);
        if (!checkSign) {
            log.info("汇付支付回调验签失败:{}", data);
            return;
        }

        // type
        String type = request.getParameter("type");
        // 根据type执行不同逻辑
        if (AdapayEventEnum.payment_succeeded.getValue().equals(type)) {
            // 支付成功
            paymentSucceeded(data);
        } else if (AdapayEventEnum.refund_succeeded.getValue().equals(type)) {
            // 退款成功
            refundSucceeded(data);
        } else if (AdapayEventEnum.refund_failed.getValue().equals(type)) {
            // 退款失败
            refundFailed(data);
        } else if (AdapayEventEnum.corp_member_failed.getValue().equals(type)) {
            // 开户失败 删除
            corpMemberFailed(data);
        } else if (AdapayEventEnum.corp_member_succeeded.getValue().equals(type)) {
            // 开户成功
            corpMemberSucceeded(data);
        } else if (AdapayEventEnum.payment_reverse_succeeded.getValue().equals(type)) {
            // 支付撤销成功
            paymentReverseSucceeded(data);
        } else if (AdapayEventEnum.payment_reverse_failed.getValue().equals(type)) {
            // 支付撤销失败
            paymentReverseFailed(data);
        } else if (AdapayEventEnum.cash_succeeded.getValue().equals(type)) {
            // 取现成功
            cashSucceeded(data);
        } else if (AdapayEventEnum.cash_failed.getValue().equals(type)) {
            // 取现失败
            cashFailed(data);
        }
    }


    /**
     * adapay支付成功回调
     *
     * @param data
     * @throws JsonProcessingException
     */
    private void paymentSucceeded(String data) throws JsonProcessingException {
        // 验签成功 保存到回调记录表中
        JSONObject jsonObject = JSON.parseObject(data);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        AdapayCallbackRecord adapayCallbackRecord = mapper.readValue(jsonObject.toJSONString(), AdapayCallbackRecord.class);

        // 支付扩展域
        adapayCallbackRecord.setExpend(jsonObject.getString("expend"));

        // 支付id
        String paymentId = jsonObject.getString("id");
        adapayCallbackRecord.setPaymentId(paymentId);

        // 订单附加说明
        JSONObject descJson = JSON.parseObject(adapayCallbackRecord.getDescription());

        // 支付回调中包含的场景类型
        String scenarioType = descJson.getString("type");
        adapayCallbackRecord.setPayScenario(scenarioType);

        // 支付回调中包含的会员id
        String memberId = descJson.getString("memberId");
        adapayCallbackRecord.setMemberId(memberId);

        // 支付回调中包含的订单编号
        String orderCode = descJson.getString("orderCode");
        adapayCallbackRecord.setOrderCode(orderCode);

        // 支付金额
        BigDecimal amount = adapayCallbackRecord.getPayAmt();

        // 保存到数据库
        adapayCallbackRecordService.saveAdapayCallbackRecord(adapayCallbackRecord);

        // 保存MemberAdapayRecord
        MemberAdapayRecord memberAdapayRecord = new MemberAdapayRecord();
        memberAdapayRecord.setMemberId(memberId);
        memberAdapayRecord.setPaymentId(paymentId);
        memberAdapayRecord.setPaymentOrderNo(adapayCallbackRecord.getOutTransId());
        memberAdapayRecord.setScenarioType(scenarioType);
        memberAdapayRecord.setPayAmt(amount);
        memberAdapayRecord.setRefundAmt(BigDecimal.ZERO);
        memberAdapayRecord.setSpendAmt(BigDecimal.ZERO);
        memberAdapayRecord.setFreezeAmt(BigDecimal.ZERO);
        memberAdapayRecord.setBalanceAmt(amount);
        memberAdapayRecordService.insertSelective(memberAdapayRecord);

        // 微信支付订单 记录会员交易流水
        MemberTransactionRecord record = MemberTransactionRecord.builder()
                .orderCode(orderCode)
                .scenarioType(scenarioType)
                .memberId(memberId)
                .actionType(ActionTypeEnum.FORWARD.getValue())
                .payMode(PayModeEnum.PAYMENT_OF_WECHATPAY.getValue())
                .paymentInstitutions(PaymentInstitutionsEnum.ADAPAY.getValue())
                .amount(amount) // 单位元
                .outTradeNo(adapayCallbackRecord.getPartyOrderId())
                .transactionId(adapayCallbackRecord.getOutTransId())
                .build();
        memberTransactionRecordService.insertSelective(record);

        if (StringUtils.equals(scenarioType, ScenarioEnum.ORDER.getValue())) { // 1-订单支付
            PaymentInfo paymentInfo = new PaymentInfo();
            paymentInfo.setPaymentId(paymentId);
            paymentInfo.setAmount(amount.toString());

            // 记录订单支付流水
            OrderPayRecord orderPayRecord = OrderPayRecord.builder()
                    .orderCode(orderCode)
                    .payMode(OrderPayRecordEnum.WECHATPAY_PAYMENT.getValue())
                    .paymentId(paymentId)
                    .payAmount(amount)
                    .acquirer(AcquirerEnum.ADAPAY.getValue())
                    .deductionRecord(JSON.toJSONString(paymentInfo))
                    .createBy(memberId)
                    .delFlag(DelFlagEnum.NORMAL.getValue())
                    .build();
            orderPayRecordService.batchInsert(Lists.newArrayList(orderPayRecord));

            // 更新冻结金额 支付成功后全部冻结
            CompletableFuture.runAsync(() -> {
                try {
                    memberAdapayRecordService.updateFreezeAmount(paymentId, amount);
                } catch (Exception e) {
                    log.error("更新冻结金额 支付成功后全部冻结error", e);
                }
            });

            // 支付订单成功
            PayOrderSuccessCallbackDTO callbackDTO = PayOrderSuccessCallbackDTO.builder()
                    .orderCode(orderCode)
                    .payAmount(amount)
                    .payMode(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())
                    .acquirer(AcquirerEnum.ADAPAY.getValue())
                    .build();
            // 订单支付成功 支付回调
            orderBasicInfoService.payOrderSuccessCallback(callbackDTO); // 订单在线支付成功回调

            // 异步判断是否对接了类似华为平台，如果是，走通用第三方平台启动充电逻辑
            CompletableFuture.runAsync(() -> {
                try {
                    checkThirdPartyQueryStartCharge(orderCode);
                } catch (Exception e) {
                    log.error("异步推送第三方平台启动充电逻辑 error", e);
                }
            });
        } else if (StringUtils.equals(scenarioType, ScenarioEnum.BALANCE.getValue())) { // 2-充值余额
            // 充值余额成功
            UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO();
            dto.setMemberId(memberId);
            dto.setType(MemberWalletEnum.TYPE_IN.getValue());
            dto.setSubType(MemberWalletEnum.SUBTYPE_TOP_UP.getValue());
            dto.setUpdatePrincipalBalance(amount);
            memberBasicInfoService.updateMemberBalance(dto);
        } else if (StringUtils.equals(scenarioType, ScenarioEnum.OCCUPY.getValue())) { // 占桩订单
            // 通过订单号查询出占桩订单信息
            OrderPileOccupy orderPileOccupy = orderPileOccupyService.queryByOccupyCode(orderCode);
            // 订单状态改为 1-订单完成
            orderPileOccupy.setStatus(OccupyOrderStatusEnum.ORDER_COMPLETE.getCode());
            // 支付状态改为 1-支付完成
            orderPileOccupy.setPayStatus(OccupyOrderPayStatusEnum.PAYMENT_COMPLETION.getCode());

            orderPileOccupyService.updateByPrimaryKey(orderPileOccupy);
        }
    }

    /**
     * 汇付退款成功
     */
    private void refundSucceeded(String data) {
        log.info("退款成功 data:{}", JSON.toJSONString(data));
        // 保存退款回调记录
        adapayRefundRecordService.saveAdapayRefundRecord(data);

        JSONObject jsonObject = JSON.parseObject(data);
        JSONObject reason = jsonObject.getJSONObject("reason");
        if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) {
            // 这笔支付订单原来是充值余额的，退款成功了，需要扣掉会员的本金金额
            UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO();
            String memberId = reason.getString("memberId");
            dto.setMemberId(memberId);
            dto.setUpdatePrincipalBalance(new BigDecimal(jsonObject.getString("refund_amt"))); // 更新会员本金金额，单位元
            dto.setType(MemberWalletEnum.TYPE_OUT.getValue());
            dto.setSubType(MemberWalletEnum.SUBTYPE_USER_REFUND.getValue());
            memberBasicInfoService.updateMemberBalance(dto);

            // 收到回调，删除缓存
            String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId;
            redisCache.deleteObject(redisKey);
        }
    }

    /**
     * 退款失败
     *
     * @param data
     */
    private void refundFailed(String data) {
        log.info("退款失败 data:{}", JSON.toJSONString(data));
        JSONObject jsonObject = JSON.parseObject(data);
        JSONObject reason = jsonObject.getJSONObject("reason");
        if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) {
            String memberId = reason.getString("memberId");

            // 收到回调，删除缓存
            String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId;
            redisCache.deleteObject(redisKey);
        }
    }

    /**
     * 对公账户创建失败
     */
    private void corpMemberFailed(String data) {
        log.info("对公账户创建失败 data:{}", JSON.toJSONString(data));
        // 删除表中的记录
        JSONObject jsonObject = JSON.parseObject(data);
        String memberId = jsonObject.getString("member_id");
        if (StringUtils.isBlank(memberId)) {
            return;
        }
        AdapayMemberAccount adapayMemberAccount = adapayMemberAccountService.selectByMemberId(memberId);
        if (adapayMemberAccount == null) {
            return;
        }
        adapayMemberAccount.setStatus(Constants.TWO);
        if (Objects.nonNull(jsonObject.getString("audit_desc"))) {
            adapayMemberAccount.setRemark(jsonObject.getString("audit_desc"));
        }
        // 逻辑删除记录，并删除缓存
        adapayMemberAccountService.updateAdapayMemberAccount(adapayMemberAccount);
    }

    /**
     * 对公账户创建成功
     */
    private void corpMemberSucceeded(String data) {
        log.info("对公账户创建成功 data:{}", JSON.toJSONString(data));
        JSONObject jsonObject = JSON.parseObject(data);
        String memberId = jsonObject.getString("member_id");
        if (StringUtils.isBlank(memberId)) {
            return;
        }
        AdapayMemberAccount adapayMemberAccount = new AdapayMemberAccount();
        adapayMemberAccount.setAdapayMemberId(memberId);
        adapayMemberAccount.setStatus(Constants.ONE);
        adapayMemberAccount.setDelFlag(DelFlagEnum.NORMAL.getValue());
        adapayMemberAccountService.updateAdapayMemberAccountByMemberId(adapayMemberAccount);
    }

    /**
     * 取现成功
     */
    private void cashSucceeded(String data) {
        log.info("取现成功 data:{}", JSON.toJSONString(data));
        JSONObject jsonObject = JSON.parseObject(data);
        String withdrawCode = jsonObject.getString("id");
        // 通过取现id查询取现数据
        ClearingWithdrawInfo clearingWithdrawInfo = clearingWithdrawInfoService.selectByWithdrawCode(withdrawCode);
        if (clearingWithdrawInfo != null) {
            clearingWithdrawInfo.setWithdrawStatus(Constants.ONE);
            clearingWithdrawInfo.setUpdateTime(DateUtils.getNowDate());
            clearingWithdrawInfoService.updateByPrimaryKeySelective(clearingWithdrawInfo);
        }

        // 清分账单数据更新
        List<ClearingBillInfo> clearingBillInfos = clearingBillInfoService.selectByWithdrawCode(withdrawCode);
        if (CollectionUtils.isNotEmpty(clearingBillInfos)) {
            for (ClearingBillInfo clearingBillInfo : clearingBillInfos) {
                clearingBillInfo.setBillStatus("4");
            }
            clearingBillInfoService.updateBatchSelective(clearingBillInfos);
        }
    }

    /**
     * 取现失败
     *
     * @param data
     */
    private void cashFailed(String data) {
        log.info("取现失败 data:{}", JSON.toJSONString(data));
        JSONObject jsonObject = JSON.parseObject(data);
        String withdrawCode = jsonObject.getString("id");
        // 通过取现id查询取现数据
        ClearingWithdrawInfo clearingWithdrawInfo = clearingWithdrawInfoService.selectByWithdrawCode(withdrawCode);
        clearingWithdrawInfo.setWithdrawStatus(Constants.TWO);
        clearingWithdrawInfo.setUpdateTime(DateUtils.getNowDate());
        clearingWithdrawInfoService.updateByPrimaryKeySelective(clearingWithdrawInfo);
    }

    /**
     * 支付撤销成功
     */
    private void paymentReverseSucceeded(String data) {
        log.info("支付撤销成功 data:{}", JSON.toJSONString(data));
        JSONObject jsonObject = JSON.parseObject(data);
        JSONObject reason = jsonObject.getJSONObject("reason");
        if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) {
            // 这笔支付订单原来是充值余额的，退款成功了，需要扣掉会员的本金金额
            UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO();
            String memberId = reason.getString("memberId");
            dto.setMemberId(memberId);
            dto.setUpdatePrincipalBalance(new BigDecimal(jsonObject.getString("reverse_amt"))); // 更新会员本金金额，单位元
            dto.setType(MemberWalletEnum.TYPE_OUT.getValue());
            dto.setSubType(MemberWalletEnum.SUBTYPE_USER_REFUND.getValue());
            memberBasicInfoService.updateMemberBalance(dto);

            // 收到回调，删除缓存
            String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId;
            redisCache.deleteObject(redisKey);
        }

    }

    /**
     * 支付撤销失败
     */
    private void paymentReverseFailed(String data) {
        log.info("支付撤销失败 data:{}", JSON.toJSONString(data));
        JSONObject jsonObject = JSON.parseObject(data);
        JSONObject reason = jsonObject.getJSONObject("reason");
        if (ScenarioEnum.BALANCE.getValue().equals(reason.getString("scenarioType"))) {
            String memberId = reason.getString("memberId");

            // 收到回调，删除缓存
            String redisKey = CacheConstants.MEMBER_BALANCE_REFUNDS_ARE_IN_PROGRESS + memberId;
            redisCache.deleteObject(redisKey);
        }
    }

    public Map<String, Object> payOccupyPileOrder(PayOrderDTO dto) {
        return orderPileOccupyService.payOccupyPileOrder(dto);
    }

    /**
     * 判断是否对接了类似华为平台的第三方平台，并启动充电
     * @param orderCode
     */
    private boolean checkThirdPartyQueryStartCharge(String orderCode) {
        // 根据订单号查询订单信息
        OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode);
        String stationId = orderInfo.getStationId();
        String pileSn = orderInfo.getPileSn();

        // 根据 stationId 查询 pile_sn_relation 表
        List<ThirdPartySnRelationVO> snRelations = snRelationService.selectSnRelationListByParams(stationId, pileSn, null);
        if (CollectionUtils.isEmpty(snRelations)) {
            return false;
        }
        for (ThirdPartySnRelationVO snRelation : snRelations) {
            String startMode = snRelation.getStartMode();
            String thirdPartyType = snRelation.getThirdPartyType();
            if (StringUtils.equals(Constants.ONE, startMode)) {
                // 如果 startMode 为 1，则调用第三方平台启动充电接口
                ThirdPartyCommonStartChargeDTO dto = new ThirdPartyCommonStartChargeDTO();
                dto.setPayMode(orderInfo.getPayMode());
                dto.setStationIds(Lists.newArrayList(stationId));
                dto.setPileConnectorCode(orderInfo.getPileConnectorCode());
                dto.setThirdPartyType(thirdPartyType);
                dto.setOrderCode(orderCode);
                String result = commonService.commonQueryStartCharge(dto);
                log.info("异步判断是否对接第三方平台 stationId:{}, thirdPartyType:{}, result:{}", stationId, thirdPartyType, result);
            }
        }

        // 判断是否对接了类似华为平台
        // List<ThirdPartyStationRelationVO> relationInfoList = thirdPartyStationRelationService.getRelationInfoList(stationId);
        // if (CollectionUtils.isEmpty(relationInfoList)) {
        //     return false;
        // }
        // for (ThirdPartyStationRelationVO vo : relationInfoList) {
        //     String startMode = vo.getStartMode();
        //     if (StringUtils.equals(Constants.TWO, startMode)) {
        //         continue;
        //     }
        //     ThirdPartyCommonStartChargeDTO dto = new ThirdPartyCommonStartChargeDTO();
        //     dto.setPayMode(orderInfo.getPayMode());
        //     dto.setStationIds(Lists.newArrayList(stationId));
        //     dto.setPileConnectorCode(orderInfo.getPileConnectorCode());
        //     dto.setThirdPartyType(vo.getThirdPartyType());
        //
        //     String result = commonService.commonQueryStartCharge(dto);
        //     log.info("异步判断是否对接第三方平台 result:{}", result);
        // }
        return true;
    }
}
