package com.kym.service.miniapp.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.kym.common.cache.PlatformCache;
import com.kym.common.constant.ResponseEnum;
import com.kym.common.exception.BusinessException;
import com.kym.common.utils.CommUtil;
import com.kym.common.utils.OrderUtils;
import com.kym.entity.admin.Activity;
import com.kym.entity.admin.ConnectorInfo;
import com.kym.entity.admin.EquipmentInfo;
import com.kym.entity.common.RedisKeys;
import com.kym.entity.miniapp.*;
import com.kym.entity.miniapp.delay.DelayChargeOrder;
import com.kym.entity.platform.response.PlatformBusinessPolicy;
import com.kym.service.admin.ConnectorInfoService;
import com.kym.service.admin.EquipmentInfoService;
import com.kym.service.admin.EquipmentRelationService;
import com.kym.service.admin.StationWhitelistConfigService;
import com.kym.service.admin.StationWhitelistService;
import com.kym.service.cache.KymCache;
import com.kym.service.jobs.DelayService;
import com.kym.service.miniapp.*;
import com.kym.service.platform.PlatformApiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author skyline
 * @description 充电
 * @date 2023-07-29 14:24
 */
@Service
@DS("db-miniapp")
public class ChargeServiceImpl implements ChargeService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ChargeServiceImpl.class);
    public final StringRedisTemplate redisTemplate;
    private final EquipmentRelationService equipmentRelationService;
    private final EquipmentInfoService equipmentInfoService;
    private final ConnectorInfoService connectorInfoService;
    private final ChargeOrderService chargeOrderService;
    private final OrderRechargeRightsService orderRechargeRightsService;
    private final UserRechargeRightsService userRechargeRightsService;
    private final UserCouponService userCouponService;
    private final OrderCouponService orderCouponService;
    private final AccountService accountService;
    private final PlatformApiService platformApiService;
    private final DelayService<DelayChargeOrder> startDelayService;
    private final DelayService<DelayChargeOrder> stopDelayService;
    private final StationWhitelistService stationWhitelistService;
    private final StationWhitelistConfigService stationWhitelistConfigService;

    public ChargeServiceImpl(EquipmentRelationService equipmentRelationService,
                             EquipmentInfoService equipmentInfoService,
                             ConnectorInfoService connectorInfoService,
                             ChargeOrderService chargeOrderService,
                             OrderRechargeRightsService orderRechargeRightsService,
                             UserRechargeRightsService userRechargeRightsService,
                             UserCouponService userCouponService,
                             OrderCouponService orderCouponService,
                             AccountService accountService,
                             PlatformApiService platformApiService,
                             @Qualifier("StartChargeDelayJob") @Lazy DelayService<DelayChargeOrder> startDelayService,
                             @Qualifier("StopChargeDelayJob") @Lazy DelayService<DelayChargeOrder> stopDelayService,
                             StationWhitelistService stationWhitelistService,
                             StationWhitelistConfigService stationWhitelistConfigService,
                             StringRedisTemplate redisTemplate) {
        this.equipmentRelationService = equipmentRelationService;
        this.equipmentInfoService = equipmentInfoService;
        this.connectorInfoService = connectorInfoService;
        this.chargeOrderService = chargeOrderService;
        this.orderRechargeRightsService = orderRechargeRightsService;
        this.userRechargeRightsService = userRechargeRightsService;
        this.userCouponService = userCouponService;
        this.orderCouponService = orderCouponService;
        this.accountService = accountService;
        this.platformApiService = platformApiService;
        this.startDelayService = startDelayService;
        this.stopDelayService = stopDelayService;
        this.stationWhitelistService = stationWhitelistService;
        this.stationWhitelistConfigService = stationWhitelistConfigService;
        this.redisTemplate = redisTemplate;
    }


    /**
     * 预约充电改立即充电
     *
     * @param connectorId
     * @return
     */
    @Override
    public Map<String, String> immediatelyCharge(String connectorId) {
        var userId = StpUtil.getLoginIdAsLong();
        cancelBooking();
        return queryStartCharge(userId, connectorId, null, null, false, null, null);
    }

    /**
     * 修改预约充电时间
     *
     * @param startChargeSeq
     * @param startTime
     * @return
     */
    @Override
    public void modifyBookingTime(String startChargeSeq, LocalDateTime startTime) {
        // 预约充电队列更新
        var chargeOrder = chargeOrderService.lambdaQuery().eq(ChargeOrder::getStartChargeSeq, startChargeSeq).eq(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_预约中).one();
        if (chargeOrder == null) {
            throw new BusinessException("预约订单不存在");
        }
        chargeOrder.setStartTime(startTime);
        chargeOrder.setEndTime(null);
        chargeOrderService.lambdaUpdate().eq(ChargeOrder::getStartChargeSeq, startChargeSeq).set(ChargeOrder::getStartTime, startTime).set(ChargeOrder::getEndTime, null).update();
        // 删除队列中原来的数据
        startDelayService.removeFromDelayQueue(startChargeSeq);
        stopDelayService.removeFromDelayQueue(startChargeSeq);
        // 向队列中添加新的数据
        var delayChargeOrder = new DelayChargeOrder();
        BeanUtils.copyProperties(chargeOrder, delayChargeOrder);
        var success = startDelayService.addToDelayQueue(delayChargeOrder);
        if (!success) {
            throw new BusinessException("修改预约时间失败");
        }
    }


    /**
     * 取消预约
     */
    @Override
    public void cancelBooking() {
        var userId = StpUtil.getLoginIdAsLong();
        var chargeOrder = chargeOrderService.lambdaQuery()
                .eq(ChargeOrder::getUserId, userId)
                .eq(ChargeOrder::getIsBooking, ChargeOrder.IS_BOOKING_是)
                .eq(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_预约中)
                .one();
        cancelBookByChargeOrder(chargeOrder);
    }

    /**
     * 取消预约
     */
    @Override
    @Async
    public void cancelBookingByConnector(String connectorId) {
        var chargeOrder = chargeOrderService.lambdaQuery()
                .eq(ChargeOrder::getConnectorId, connectorId)
                .eq(ChargeOrder::getIsBooking, ChargeOrder.IS_BOOKING_是)
                .eq(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_预约中)
                .one();
        cancelBookByChargeOrder(chargeOrder);
    }

    /**
     * 取消预约订单
     *
     * @param chargeOrder 预约订单
     */
    public void cancelBookByChargeOrder(ChargeOrder chargeOrder) {
        if (chargeOrder != null) {
            // 清除启动/停止队列信息
            startDelayService.removeFromDelayQueue(chargeOrder.getStartChargeSeq());
            stopDelayService.removeFromDelayQueue(chargeOrder.getStartChargeSeq());
            // 修改订单状态为取消
            chargeOrderService.lambdaUpdate()
                    .set(ChargeOrder::getOrderStatus, ChargeOrder.ORDER_STATUS_取消)
                    .set(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_已取消)
                    .eq(ChargeOrder::getStartChargeSeq, chargeOrder.getStartChargeSeq())
                    .update();
            LOGGER.info("取消/清除预约订单：{}", chargeOrder.getStartChargeSeq());
        } else {
            LOGGER.info("用户没有预约中的订单");
        }
    }


    /**
     * 启动充电
     *
     * @param connectorId
     * @param userRechargeRightsId
     * @param isBooking
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    @DSTransactional(rollbackFor = Exception.class)
    public Map<String, String> queryStartCharge(Long userId, String connectorId, Long userRechargeRightsId, Long userCouponId, Boolean isBooking, LocalDateTime startTime, LocalDateTime endTime) {
        connectorId = KymCache.INSTANCE.getConnectorId(connectorId);
        var stationId = KymCache.INSTANCE.getStationIdByEquipmentIdOrConnectorId(connectorId);
        LOGGER.info("用户：{},站点：{}，设备：{}请求充电", userId, stationId, connectorId);
        var account = checkCharge(userId, connectorId, stationId, isBooking, startTime);

        // 是否有之前预约充电创建的订单记录，有则直接用，没有则创建
        ChargeOrder order = chargeOrderService.lambdaQuery()
                .eq(ChargeOrder::getUserId, userId)
                .eq(ChargeOrder::getConnectorId, connectorId)
                .eq(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_预约中)
                .one();

        if (order == null) {
            // 充电订单号/设备认证号
            String startChargeSeq = OrderUtils.getOrderNo(PlatformCache.INSTANCE.getPlatformByName(PlatformCache.INSTANCE.getPlatformNameByConnectorId(connectorId)).getOperatorId());

            // 组装订单数据
            order = new ChargeOrder();
            order.setIsBooking(isBooking ? ChargeOrder.IS_BOOKING_是 : ChargeOrder.IS_BOOKING_否);
            order.setUserId(userId);
            order.setStationId(stationId);
            order.setStartChargeSeq(startChargeSeq);
            order.setConnectorId(connectorId);
            order.setOrderStatus(ChargeOrder.ORDER_STATUS_未知);
            order.setChargeStatus(ChargeOrder.CHARGE_STATUS_启动中);

            // 订单充值权益
            if (!CommUtil.isEmptyOrNull(userRechargeRightsId)) {
                var userRechargeRights = userRechargeRightsService.lambdaQuery().eq(UserRechargeRights::getUserId, userId).eq(UserRechargeRights::getId, userRechargeRightsId).one();
                if (userRechargeRights != null) {
                    // 设置订单优惠类型
                    order.setDiscountType(Activity.DISCOUNT_TYPE_服务费折扣权益);

                    var orderRechargeRights = new OrderRechargeRights()
                            .setUserId(userId)
                            .setStartChargeSeq(startChargeSeq)
                            .setActivityId(userRechargeRights.getActivityId())
                            .setRightsId(userRechargeRights.getRightsId())
                            .setUserRightsId(userRechargeRights.getId())
                            .setDiscount(userRechargeRights.getDiscount());
                    orderRechargeRightsService.save(orderRechargeRights);
                }
            }

            // 优惠券
            if (!CommUtil.isEmptyOrNull(userCouponId)) {
                var userCoupon = userCouponService.lambdaQuery().eq(UserCoupon::getUserId, userId).eq(UserCoupon::getId, userCouponId).one();
                if (userCoupon != null) {
                    // 设置订单优惠类型
                    order.setDiscountType(Activity.DISCOUNT_TYPE_优惠券);

                    var orderCoupon = new OrderCoupon()
                            .setUserId(userId)
                            .setStartChargeSeq(startChargeSeq)
                            .setCouponType(userCoupon.getCouponType())
                            .setActivityId(userCoupon.getActivityId())
                            .setCouponId(userCoupon.getCouponId())
                            .setUserCouponId(userCoupon.getId())
                            .setDiscount(userCoupon.getDiscount());
                    orderCouponService.save(orderCoupon);
                }
            }

            // 保存订单信息
            chargeOrderService.save(order);
        }

        // 如果是预约订单，则将订单放入预约充电延迟队列
        if (isBooking) {
            order = order.setStartTime(startTime).setChargeStatus(ChargeOrder.CHARGE_STATUS_预约中).setIsBooking(ChargeOrder.IS_BOOKING_是);

            // 如果有设置结束时间,取消时记得删
            if (!CommUtil.isEmptyOrNull(endTime)) {
                order.setEndTime(endTime);
            }
            chargeOrderService.lambdaUpdate()
                    .set(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_预约中)
                    .set(ChargeOrder::getIsBooking, order.getIsBooking())
                    .set(ChargeOrder::getStartTime, startTime)
                    .set(!CommUtil.isEmptyOrNull(endTime), ChargeOrder::getEndTime, endTime)
                    .eq(ChargeOrder::getUserId, userId)
                    .eq(ChargeOrder::getStartChargeSeq, order.getStartChargeSeq())
                    .update();

            var delayChargeOrder = new DelayChargeOrder();
            BeanUtils.copyProperties(order, delayChargeOrder);

            var flag = startDelayService.addToDelayQueue(delayChargeOrder.setStartTime(startTime));
            if (flag) {
                // 如果有结束时间，将订单放入结束充电延迟队列中
                if (endTime != null) {
                    stopDelayService.addToDelayQueue(delayChargeOrder.setEndTime(endTime));
                }
                // 切换数据源,修改设备状态为预约中
                updateEquipmentAndConnectorStatus(connectorId);
                LOGGER.info("预约充电成功，用户：{}，订单号：{}", userId, order.getStartChargeSeq());
                return Map.of("startChargeSeq", order.getStartChargeSeq());
            } else {
                LOGGER.error("预约充电失败，用户：{}，订单号：{}", userId, order.getStartChargeSeq());
                throw new BusinessException("充电预约失败");
            }
        }

        return startCharge(order, connectorId, account.getBalance());

    }


    /**
     * 启动充电校验流程
     *
     * @param userId
     * @param connectorId
     * @param stationId
     * @param isBooking
     * @param startTime
     * @return
     */
    private Account checkCharge(Long userId, String connectorId, String stationId, Boolean isBooking, LocalDateTime startTime) {
        if (CommUtil.isEmptyOrNull(connectorId)) {
            throw new BusinessException("请输入正确的设备编号");
        }

        // 设备是否插枪
        if (KymCache.INSTANCE.getConnectorStatus(connectorId) == EquipmentInfo.SERVICE_STATUS_空闲) {
            throw new BusinessException("请插入充电枪");
        }

        if (isBooking) {
            // 设备状态必须为插枪才可以预约
            if (KymCache.INSTANCE.getConnectorStatus(connectorId) != EquipmentInfo.SERVICE_STATUS_已连接) {
                throw new BusinessException("设备状态异常");
            }
            // 预约时间不能超过未来24H
            if (TimeUnit.SECONDS.convert(Duration.between(LocalDateTime.now(), startTime)) > 3600 * 24) {
                throw new BusinessException("预约充电启动时间不能超过未来24小时");
            }
            // 预约充电通过connectorId查询预约中的订单
            var bookingOrder = chargeOrderService.lambdaQuery()
                    .eq(ChargeOrder::getUserId, userId)
                    .eq(ChargeOrder::getConnectorId, connectorId)
                    .eq(ChargeOrder::getIsBooking, ChargeOrder.IS_BOOKING_是)
                    .eq(ChargeOrder::getOrderStatus, ChargeOrder.ORDER_STATUS_未知)
                    .eq(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_预约中)
                    .one();
            if (bookingOrder != null) {
                LOGGER.error("用户：{}存在进行中的订单：{}", userId, bookingOrder.getStartChargeSeq());
                throw new BusinessException(ResponseEnum.ORDER_IN_BOOKING);
            }
        }

        // 当前用户是否有正在进行中、预约中、启动中的订单
        var chargeOrder = chargeOrderService.getChargingOrderByUserId(userId);
        if (chargeOrder != null) {
            // 预约中的订单到了启动时间则直接启动，忽略校验
            if (!(chargeOrder.getChargeStatus().equals(ChargeOrder.CHARGE_STATUS_预约中) && chargeOrder.getStartTime().isBefore(LocalDateTime.now()))) {
                LOGGER.error("用户：{}存在进行中的订单：{}", userId, chargeOrder.getStartChargeSeq());
                throw new BusinessException(ResponseEnum.ORDER_IN_PROGRESS);
            }
        }

        // 查询用户余额
        var account = accountService.getAccountByUserId(userId);
        if (account.getBalance() <= 200) {
            LOGGER.error("用户：{}余额不足2元，余额：{}", userId, account.getBalance());
            throw new BusinessException(ResponseEnum.INSUFFICIENT_USER_BALANCE);
        }

        // 白名单验证
        if (stationId != null && stationWhitelistConfigService.isWhitelistEnabled(stationId)) {
            if (!stationWhitelistService.isInWhitelist(stationId, userId)) {
                LOGGER.warn("用户：{}不在站点：{}的白名单中，拒绝充电", userId, stationId);
                throw new BusinessException(ResponseEnum.USER_NOT_IN_WHITELIST);
            }
            LOGGER.info("用户：{}在站点：{}的白名单中，验证通过", userId, stationId);
        }

        return account;
    }

    /**
     * 启动充电
     *
     * @param order
     * @param connectorId
     * @param balance
     * @return
     */
    private Map<String, String> startCharge(ChargeOrder order, String connectorId, int balance) {

        // 请求设备认证
        var equipAuth = platformApiService.queryEquipAuth(PlatformCache.INSTANCE.getPlatformNameByConnectorId(connectorId), connectorId, order.getStartChargeSeq());

        if (equipAuth.containsKey("SuccStat") && equipAuth.getIntValue("SuccStat") == 0) {
            // 启动充电
            JSONObject startCharge;

            try {
                // 二维码文本
                var qrCode = "";
                startCharge = platformApiService.queryStartCharge(PlatformCache.INSTANCE.getPlatformNameByConnectorId(connectorId), order.getStartChargeSeq(), connectorId, qrCode, balance);
            } catch (Exception e) {
                // 这里可能超时，忽略
                LOGGER.error("启动充电异常，订单：{}，异常信息：{}", order.getStartChargeSeq(), e.getMessage());
                // 启动充电超时，更新订单状态为取消
                chargeOrderService.lambdaUpdate()
                        .set(ChargeOrder::getOrderStatus, ChargeOrder.ORDER_STATUS_失败)
                        .set(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_已取消)
                        .set(ChargeOrder::getStopReason, ChargeOrder.STOP_REASON_启动充电异常)
                        .eq(ChargeOrder::getStartChargeSeq, order.getStartChargeSeq())
                        .update();
                return Map.of("startChargeSeq", order.getStartChargeSeq());
            }

            if (startCharge != null && startCharge.containsKey("SuccStat") && startCharge.getIntValue("SuccStat") == 0) {
                // 启动成功，更新充电订单状态
                chargeOrderService.lambdaUpdate()
                        .set(ChargeOrder::getIsBooking, ChargeOrder.IS_BOOKING_否)
                        .set(ChargeOrder::getChargeStatus, startCharge.getIntValue("StartChargeSeqStat"))
                        .eq(ChargeOrder::getStartChargeSeq, order.getStartChargeSeq())
                        .update();
                return Map.of("startChargeSeq", order.getStartChargeSeq());
            } else {
                // 启动充电失败
                LOGGER.error("设备启动充电失败：{}", startCharge);
                var failReason = equipAuth.getIntValue("FailReason");
                // 朗新和EN+分开处理
                if ("LONGSHINE".equals(PlatformCache.INSTANCE.getPlatformNameByConnectorId(connectorId))) {
                    switch (failReason) {
                        case 1 -> // 设备不存在
                                throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_NOT_EXIST);
                        case 2 -> // 设备离线
                                throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_OFFLINE);
                        case 3 -> // 充电枪未与车连接
                                throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_NOT_CONNECTED);
                        case 4 -> // 余额不足
                                throw new BusinessException(ResponseEnum.INSUFFICIENT_USER_BALANCE);
                        case 5 -> // 设备故障
                                throw new BusinessException("设备故障");
                        case 6 -> // 设备异常
                                throw new BusinessException("设备异常");
                        case 7 -> // 参数错误
                                throw new BusinessException("参数错误");
                        case 8 -> // 二维码校验失败
                                throw new BusinessException("二维码校验失败");
                        case 9 -> // 设备已在服务中
                                throw new BusinessException("设备已在服务中");
                        case 10 -> // 系统异常
                                throw new BusinessException("系统异常");
                        case 11 -> // 请求太频繁
                                throw new BusinessException("请求太频繁");
                    }
                }
                if ("EN_PLUS".equals(PlatformCache.INSTANCE.getPlatformNameByConnectorId(connectorId))) {
                    switch (failReason) {
                        case 1 -> // 设备不存在
                                throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_NOT_EXIST);
                        case 2 -> // 设备离线
                            // todo 设备离线，加入重试机制
                                throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_OFFLINE);
                        case 3 -> // 存在未完成的订单
                                throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_EXIST_ORDER_UNFINISHED);
                        case 4 -> // 此订单为停车中
                                throw new BusinessException(ResponseEnum.PLATFORM_ORDER_IS_PARKING);
                        case 5 -> // 此订单已关闭
                                throw new BusinessException(ResponseEnum.PLATFORM_ORDER_CLOSED);
                        case 6 -> // 设备未插枪
                                throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_NOT_CONNECTED);
                        case 7 -> // 预充金额存在且小于1元
                                throw new BusinessException(ResponseEnum.INSUFFICIENT_USER_BALANCE);
                    }
                }

                throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_START_FAIL);
            }
        } else {
            // 设备认证失败
            LOGGER.error("设备认证失败：{}", equipAuth);
            switch (equipAuth.getIntValue("FailReason")) {
                case 1 -> // 设备未插枪
                        throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_NOT_CONNECTED);

                case 2 -> // 设备检测失败
                        throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_CHECK_FAIL);
            }
            // 订单标记为失败已结束
            chargeOrderService.lambdaUpdate()
                    .set(ChargeOrder::getOrderStatus, ChargeOrder.ORDER_STATUS_失败)
                    .set(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_已结束)
                    .set(ChargeOrder::getStopReason, ChargeOrder.STOP_REASON_启动充电异常)
                    .eq(ChargeOrder::getStartChargeSeq, order.getStartChargeSeq())
                    .update();
            throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_AUTH_FAIL);
        }
    }


    /**
     * 修改充电桩状态（这里@DS使用AOP实现，切换数据源需要单独抽出方法，这里@DS不生效，改为手动切换）
     *
     * @param connectorId
     */
    @Override
    public void updateEquipmentAndConnectorStatus(String connectorId) {
        // 手动切换数据源
        DynamicDataSourceContextHolder.push("db-admin");
        equipmentInfoService.lambdaUpdate().set(EquipmentInfo::getServiceStatus, EquipmentInfo.SERVICE_STATUS_预约中).eq(EquipmentInfo::getEquipmentId, connectorId.substring(0, 16)).update();
        connectorInfoService.lambdaUpdate().set(ConnectorInfo::getStatus, EquipmentInfo.SERVICE_STATUS_预约中).eq(ConnectorInfo::getConnectorId, connectorId).update();
        DynamicDataSourceContextHolder.poll();
    }


    /**
     * 请求设备充电状态
     *
     * @return
     */
    @Override
    public ChargeOrder queryEquipChargeStatus() {
        var userId = StpUtil.getLoginIdAsLong();
        var chargeOrder = chargeOrderService.getChargingOrderByUserId(userId);
        if (chargeOrder != null) {
            // 查询redis缓存,有数据则更新chargeOrder再返回
            var orderDataStr = redisTemplate.opsForHash().get(RedisKeys.CHARGE_ORDER_EQUIP_CHARGE_STATUS, chargeOrder.getStartChargeSeq());
            if (CommUtil.isNotEmptyAndNull(orderDataStr)) {
                var data = JSONObject.parseObject(orderDataStr.toString(), ChargeOrder.class);
                // 更新订单信息
                chargeOrder.setSoc(data.getSoc());
                chargeOrder.setTotalPower(data.getTotalPower());
                chargeOrder.setTotalMoney((data.getTotalMoney()));
                chargeOrder.setElecMoney((data.getElecMoney()));
                chargeOrder.setServiceMoney((data.getServiceMoney()));
                chargeOrder.setSumPeriod(data.getSumPeriod());
                chargeOrder.setChargeDetail(data.getChargeDetail());
                chargeOrder.setChargeStatus(data.getChargeStatus());
            }
            return chargeOrder;
        } else {
            LOGGER.debug("用户：{}无进行中的订单", userId);
            return null;
        }
    }

    /**
     * 获取设备接口编号和站点编号
     *
     * @param connectorId 充电桩id，短编号等
     * @return
     */
    @DS("db-admin")
    @Deprecated
    public Map<String, String> getConnectorIdAndStationId(String connectorId) {
        var stationId = "";
        if (connectorId.length() == 17) {
            var equipmentRelation = equipmentRelationService.getByConnectorId(connectorId);
            stationId = equipmentRelation.getStationId();
        } else if (connectorId.length() == 6) {
            // 查询EN+设备SN
            var equipmentRelation = equipmentRelationService.getByShortId(connectorId);
            connectorId = equipmentRelation.getConnectorId();
            stationId = equipmentRelation.getStationId();
            if (connectorId.length() == 16) {
                // 如果是16位，末尾补1作为单枪枪号
                connectorId = connectorId.concat("1");
            }
        } else {
            // 充电桩编号错误
            LOGGER.error("设备编码错误：{}", connectorId);
            throw new BusinessException(ResponseEnum.EQUIP_CONNECTOR_ID_ERROR);
        }
        return Map.of("connectorId", connectorId, "stationId", stationId);
    }

    @DS("db-admin")
    public String getConnectorId(String connectorId) {
        if (connectorId.length() == 17) {
            return connectorId;
        } else if (connectorId.length() == 6) {
            // 查询EN+设备SN
            var equipmentRelation = equipmentRelationService.getByShortId(connectorId);
            connectorId = equipmentRelation.getConnectorId();
            if (connectorId.length() == 16) {
                // 如果是16位，末尾补1作为单枪枪号
                connectorId = connectorId.concat("1");
            }
        } else {
            // 充电桩编号错误
            LOGGER.error("设备编码错误：{}", connectorId);
            throw new BusinessException(ResponseEnum.EQUIP_CONNECTOR_ID_ERROR);
        }
        return connectorId;
    }

    /**
     * 请求停止充电
     *
     * @param connectorId
     */
    @Override
    public void queryStopCharge(long userId, String connectorId) {
        connectorId = getConnectorId(connectorId);
        LOGGER.info("用户：{},设备：{}请求停止充电", userId, connectorId);
        // 设备状态校验，如果设备离线则提示用户
        if (EquipmentInfo.SERVICE_STATUS_离线 == KymCache.INSTANCE.getConnectorStatus(connectorId)) {
            throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_OFFLINE);
        }
        // 查询充电订单
        var chargeOrder = chargeOrderService.lambdaQuery()
                .eq(ChargeOrder::getUserId, userId)
                .eq(ChargeOrder::getConnectorId, connectorId)
                .eq(ChargeOrder::getChargeStatus, ChargeOrder.CHARGE_STATUS_充电中)
                .one();
        if (chargeOrder == null) {
            // 记录失败原因
            LOGGER.error("用户：{}请求停止充电异常，设备：{}无进行中的订单", userId, connectorId);
            throw new BusinessException(ResponseEnum.NO_ORDER_IN_PROGRESS);
        }
        var data = platformApiService.queryStopCharge(PlatformCache.INSTANCE.getPlatformNameByConnectorId(connectorId), chargeOrder.getStartChargeSeq(), connectorId);
        if (data.containsKey("SuccStat") && data.getIntValue("SuccStat") != 0) {
            // 记录失败原因
            LOGGER.error("订单：{}停止充电失败，返回结果:{}", chargeOrder.getStartChargeSeq(), data);
            throw new BusinessException(ResponseEnum.PLATFORM_EQUIP_STOP_FAIL);
        }
        // 这里不更新订单状态，等待互联互通平台推送停止充电结果信息再处理

    }

    /**
     * 请求设备计费策略
     *
     * @param connectorId
     * @return
     */
    @Override
    public PlatformBusinessPolicy queryEquipBusinessPolicy(String connectorId) {
        var platformName = PlatformCache.INSTANCE.getPlatformNameByConnectorId(connectorId);
        var equipBizSeq = OrderUtils.getOrderNo(PlatformCache.INSTANCE.getPlatformByName(platformName).getOperatorId());
        var data = platformApiService.queryEquipBusinessPolicy(platformName, equipBizSeq, connectorId);
        return data.toJavaObject(PlatformBusinessPolicy.class);
    }

}
