package cn.iocoder.yudao.module.system.service.robot.job;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.api.robot.websocket.RobotStatusDataPoseDTO;
import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotStatusCodeConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.controller.admin.config.vo.CommonConfigVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskDetailAddVO;
import cn.iocoder.yudao.module.system.dal.dataobject.config.CommonConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotChargeLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
import cn.iocoder.yudao.module.system.dal.mysql.config.CommonConfigMapper;
import cn.iocoder.yudao.module.system.dal.mysql.information.DeviceInformationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotChargeLogMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotInformationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskMapper;
import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum;
import cn.iocoder.yudao.module.system.enums.config.CommandConfigTypeEnum;
import cn.iocoder.yudao.module.system.enums.device.DeviceTypeEnum;
import cn.iocoder.yudao.module.system.enums.device.DeviceUseStatusEnum;
import cn.iocoder.yudao.module.system.enums.redis.RobotCacheLockEnum;
import cn.iocoder.yudao.module.system.enums.robot.*;
import cn.iocoder.yudao.module.system.enums.robot.charge.ChargeModelEnum;
import cn.iocoder.yudao.module.system.service.robot.pathplanning.RobotPathPlanningService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class AutoChargeServiceImpl implements AutoChargeService {

    @Resource
    private RobotInformationMapper robotInformationMapper;

    @Resource
    private CommonConfigMapper configMapper;

    @Resource
    private RobotChargeLogMapper chargeLogMapper;

    @Resource
    private DeviceInformationMapper deviceInformationMapper;

    @Autowired
    private RobotTaskDetailMapper robotTaskDetailMapper;

    @Autowired
    private RobotTaskMapper robotTaskMapper;

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private ZnConfigConstant znConfigConstant;

    @Autowired
    private RobotPathPlanningService robotPathPlanningService;

    /**
     * 自动充电
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void autoChargeJob() {
        TenantContextHolder.setTenantId(1L);

        CommonConfigDO commonConfigDO = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
                .eq(CommonConfigDO::getConfigType, CommandConfigTypeEnum.CHARG_CONFIG.getType()));

        if (ObjectUtil.isEmpty(commonConfigDO)) {
            log.info("暂未配置充电信息");
            return;
        }

        CommonConfigVO chargeConfig = JSONUtil.toBean(commonConfigDO.getConfigStr(), CommonConfigVO.class);

        List<RobotInformationDO> robots = robotInformationMapper.selectList(new LambdaQueryWrapperX<RobotInformationDO>()
                .eq(RobotInformationDO::getRobotStatus, RobotStatusEnum.STAND_BY.getType())
                .eq(RobotInformationDO::getRobotTaskModel, RobotTaskModelEnum.NORMAL.getType()));
        if (ObjectUtil.isEmpty(robots)) {
            log.info("充电任务,没有空闲机器人");
            return;
        }

        List<DeviceInformationDO> deviceInformationDOS = deviceInformationMapper.selectList(new LambdaQueryWrapperX<DeviceInformationDO>()
                .eq(DeviceInformationDO::getDeviceEnable, ZeroOneEnum.ONE.getType())
                .eq(DeviceInformationDO::getDeviceUseStatus, ZeroOneEnum.ZERO.getType())
                .eq(DeviceInformationDO::getDeviceType, DeviceTypeEnum.CHARGING_STATION.getType()));

        if (ObjectUtil.isEmpty(deviceInformationDOS)) {
            log.info("充电任务,没有空闲的充电桩");
            robots = getNeedChargeRobot(robots, chargeConfig);
            log.info("需要充电的车辆 :{}", JSON.toJSONString(robots));
            if (ObjectUtil.isEmpty(robots)) {
                return;
            }

            List<RobotInformationDO> chargeIngRobots = robotInformationMapper.selectList(new LambdaQueryWrapperX<RobotInformationDO>()
                    .eq(RobotInformationDO::getRobotStatus, RobotStatusEnum.CHARGE.getType())
                    .eq(RobotInformationDO::getRobotTaskModel, RobotTaskModelEnum.NORMAL.getType()));
            if (ObjectUtil.isEmpty(chargeIngRobots)) {
                log.info("没有充电中的车辆");
                return;
            }
            List<RobotInformationDO>  moveToWaitRobots = getCanLeaveChargingRobots(chargeIngRobots, chargeConfig, robots.size());
            if (ObjectUtil.isEmpty(moveToWaitRobots)) {
                log.info("充电中的车辆未达到离开的阀值");
                return;
            }
            robotPathPlanningService.moveRobotToWait(moveToWaitRobots);
            return;
        }

        List<String> robotNos = robots.stream()
                .map(RobotInformationDO::getRobotNo)
                .collect(Collectors.toList());
        //近期有充满电的机器人编号
        List<String> chargeFullNos = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(chargeConfig.getChanceCycle())) {
            //查询充满电
            chargeFullNos = chargeLogMapper.getChargeFullRobotNos(chargeConfig.getChanceCycle(), robotNos);
        }

        List<RobotTaskDetailDO> taskDetailDOS = robotTaskDetailMapper.getChargeTaskDetail();
        Map<String, List<RobotTaskDetailDO>> detailMap = null;
        if (ObjectUtil.isNotEmpty(taskDetailDOS)) {
            detailMap = taskDetailDOS.stream().collect(Collectors.groupingBy(RobotTaskDetailDO::getRobotNo));
        }

        List<RobotChargeLogDO> logs = new ArrayList<>();
        List<RobotTaskDO> tasks = new ArrayList<>();
        List<RobotTaskDetailAddVO> taskDetails = new ArrayList<>();
        //组装充电任务
        assembleChargeTask(robots, deviceInformationDOS, chargeConfig, chargeFullNos, logs, detailMap, tasks, taskDetails);

        if (ObjectUtil.isEmpty(logs)) {
            log.info("没有需要执行的充电任务");
            return;
        }

        if (ObjectUtil.isNotEmpty(tasks)) {
            robotTaskMapper.insertBatch(tasks);
            List<RobotTaskDetailDO> bean = BeanUtils.toBean(taskDetails, RobotTaskDetailDO.class);
            robotTaskDetailMapper.insertBatch(bean);
        }

        chargeLogMapper.insert(logs);

        robotPathPlanningService.sendChargeTaskToPP(logs, taskDetailDOS, robots);

        //改成异步
        logs.stream().forEach(v -> {
            String chargeModelKey = RobotTaskChcheConstant.ROBOT_CHARGE_MODEL + v.getRobotNo();
            redisUtil.set(chargeModelKey, v.getChargeModel());
        });

    }

    /**
     * 查询充电达到阀值，能离开的车辆
     *
     * @param robots
     * @param chargeConfig sum 需要移动的车辆数量
     * @return
     */
    private List<RobotInformationDO> getCanLeaveChargingRobots(List<RobotInformationDO> robots, CommonConfigVO chargeConfig, int sum) {
        List<RobotInformationDO> needChargeRobots = new ArrayList<>();
        Map<String, Integer> map = new HashMap<>();
        Map<String, RobotInformationDO> robotMap = new HashMap<>();
        for (RobotInformationDO robot : robots) {
            String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robot.getMacAddress();
            String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED + robot.getMacAddress();
            Object taskStatus = redisUtil.get(taskStatusKey);
            if (ObjectUtil.isEmpty(taskStatus) || !RobotStatusCodeConstant.CAN_DO_TASK.equals(Boolean.parseBoolean(String.valueOf(taskStatus)))) {
                robot.setRobotStatus(RobotStatusEnum.DOING.getType());
                log.info("车机上报不允许接任务 :{}", robot.getRobotNo());
                continue;
            }

            Object cargoDetected = redisUtil.get(cargoDetectedKey);
            if (ObjectUtil.isEmpty(cargoDetected) || RobotStatusCodeConstant.CARGO_DETECTED.equals(Boolean.parseBoolean(String.valueOf(cargoDetected)))) {
                robot.setRobotStatus(RobotStatusEnum.DOING.getType());
                log.info("车机上报传感器被按下--不允许接任务 :{}", robot.getRobotNo());
                continue;
            }

            Boolean adequateBatteryCapacity = remainingElectricityBigger(chargeConfig, robot);
            if (adequateBatteryCapacity) {
                robot.setRobotStatus(RobotStatusEnum.STAND_BY.getType());
                String socKey = RobotTaskChcheConstant.ROBOT_INFORMATION_SOC + robot.getMacAddress();
                Object o = redisUtil.get(socKey);
                Integer soc = ObjectUtil.isEmpty(o) ? 0 : Integer.parseInt(o.toString());
                map.put(robot.getRobotNo(), soc);
                robotMap.put(robot.getRobotNo(),robot);
            }
        }

        if (ObjectUtil.isEmpty(map)) {
            return needChargeRobots;
        }

        map = map.entrySet().stream()
                .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (x1, x2) -> x2, LinkedHashMap::new));

        log.info("排序后的集合 :{}",JSON.toJSONString(map));
        for (Map.Entry<String, Integer> item : map.entrySet()) {
            if (needChargeRobots.size() > sum) {
                break;
            }
            needChargeRobots.add(robotMap.get(item.getKey()));
        }
        log.info("充电达到阀值，可以移动到等待点的车辆 :{}",JSON.toJSONString(needChargeRobots));
        return needChargeRobots;
    }

    /**
     * 查询需要充电的车辆
     *
     * @param robots
     * @return
     */
    private List<RobotInformationDO> getNeedChargeRobot(List<RobotInformationDO> robots, CommonConfigVO chargeConfig) {
        List<RobotInformationDO> needChargeRobots = new ArrayList<>();
        for (RobotInformationDO robot : robots) {
            String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robot.getMacAddress();
            String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED + robot.getMacAddress();
            Object taskStatus = redisUtil.get(taskStatusKey);
            if (ObjectUtil.isEmpty(taskStatus) || !RobotStatusCodeConstant.CAN_DO_TASK.equals(Boolean.parseBoolean(String.valueOf(taskStatus)))) {
                robot.setRobotStatus(RobotStatusEnum.DOING.getType());
                log.info("车机上报不允许接任务 :{}", robot.getRobotNo());
                continue;
            }

            Object cargoDetected = redisUtil.get(cargoDetectedKey);
            if (ObjectUtil.isEmpty(cargoDetected) || RobotStatusCodeConstant.CARGO_DETECTED.equals(Boolean.parseBoolean(String.valueOf(cargoDetected)))) {
                robot.setRobotStatus(RobotStatusEnum.DOING.getType());
                log.info("车机上报传感器被按下--不允许接任务 :{}", robot.getRobotNo());
                continue;
            }

            Boolean adequateBatteryCapacity = remainingElectricityBigger(chargeConfig, robot);
            if (!adequateBatteryCapacity) {
                needChargeRobots.add(robot);

            }
        }
        return needChargeRobots;
    }

    /**
     * 剩余电量是否大于设置的充电阀值
     *
     * @param chargeConfig
     * @param robot
     */
    private Boolean remainingElectricityBigger(CommonConfigVO chargeConfig, RobotInformationDO robot) {
        String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT + robot.getMacAddress();
        String chargeModelKey = RobotTaskChcheConstant.ROBOT_CHARGE_MODEL + robot.getRobotNo();
        Object chargeModelCache = redisUtil.get(chargeModelKey);
        Object poseCache = redisUtil.get(pose2dKey);
//        RobotStatusDataPoseDTO dataPoseDTO = JSON.parseObject((String) poseCache, RobotStatusDataPoseDTO.class);
//        log.info("充电机器人编号:{} ,信息: {}", robot.getRobotNo(), JSON.toJSONString(dataPoseDTO));

        String socKey = RobotTaskChcheConstant.ROBOT_INFORMATION_SOC + robot.getMacAddress();
        Object o = redisUtil.get(socKey);
        String soc = ObjectUtil.isEmpty(o) ? "0" : o.toString();

        if (ObjectUtil.isEmpty(poseCache) || ObjectUtil.isEmpty(o)) {
            log.info("没有点位信息/或者没有电量信息 :{}", robot.getRobotNo());
            return false;
        }

        //车子剩余电量
        BigDecimal robotRemainingElectricity = new BigDecimal(soc);
        //设置离开的电量
        BigDecimal robotEndElectricity = new BigDecimal("30");

        if (ObjectUtil.isNotEmpty(robot.getAutoCharge()) && ObjectUtil.isNotEmpty(chargeModelCache)
                && !ChargeModelEnum.FULL.getType().equals((Integer) chargeModelCache)) {
            robotEndElectricity = new BigDecimal(String.valueOf(robot.getAutoCharge()));
        } else if (ObjectUtil.isNotEmpty(chargeModelCache) && ChargeModelEnum.FULL.getType().equals((Integer) chargeModelCache)) {
            robotEndElectricity = new BigDecimal(znConfigConstant.getFullElectricity());
        } else if (ObjectUtil.isNotEmpty(chargeModelCache) && ChargeModelEnum.CHANCE.getType().equals((Integer) chargeModelCache)
                && ObjectUtil.isNotEmpty(chargeConfig.getEndAutoCharge())) {
            robotEndElectricity = new BigDecimal(String.valueOf(chargeConfig.getChanceChargeEnd()));
        } else if (ObjectUtil.isNotEmpty(chargeConfig.getEndAutoCharge())) {
            robotEndElectricity = new BigDecimal(String.valueOf(chargeConfig.getEndAutoCharge()));
        }

        if (robotRemainingElectricity.compareTo(robotEndElectricity) >= 0) {
            return true;
        } else {
            log.info("机器人正在充电,还没达到充电设置的电量,暂不能接任务:{} ", robot.getRobotNo());
        }
        return false;
    }

    public Integer getSocByMac(RobotInformationDO robot) {
        String socKey = RobotTaskChcheConstant.ROBOT_INFORMATION_SOC + robot.getMacAddress();
        Object socObject = redisUtil.get(socKey);

        if (ObjectUtil.isEmpty(socObject)) {
            log.info("当前机器人查不到电量信息,所以不执行充电 :{}", robot.getRobotNo());
            return null;
        }
        String[] split = socObject.toString().split("\\.");
        return Integer.valueOf(split[0]);
    }

    /**
     * 组装充电任务
     *
     * @param robots
     * @param deviceInformationDOS
     * @param chargeConfig
     * @param chargeFullNos
     * @param logs
     * @param detailMap
     */
    public void assembleChargeTask(List<RobotInformationDO> robots, List<DeviceInformationDO> deviceInformationDOS,
                                   CommonConfigVO chargeConfig, List<String> chargeFullNos,
                                   List<RobotChargeLogDO> logs, Map<String, List<RobotTaskDetailDO>> detailMap,
                                   List<RobotTaskDO> tasks, List<RobotTaskDetailAddVO> taskDetails) {
        //判断机器人身上的电量少于设定的电量
        for (RobotInformationDO robot : robots) {
            String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT + robot.getMacAddress();
            Object poseCache = redisUtil.get(pose2dKey);
            if (ObjectUtil.isEmpty(poseCache)) {
                log.info("查不到车辆的点位信息 :{}", robot.getRobotNo());
                continue;
            }

            Integer electricity = getSocByMac(robot);
            if (ObjectUtil.isEmpty(electricity)) {
                continue;
            }

            if (ObjectUtil.isEmpty(deviceInformationDOS)) {
                log.info("充电桩分配完成 :{}", robot.getRobotNo());
                break;
            }

            DeviceInformationDO deviceInformationDO = deviceInformationDOS.stream()
                    .filter(v -> v.getDeviceAttribute().equals(robot.getChargeType())
                            && robot.getFloorAreaJson().contains(v.getPositionMapId()))
                    .findFirst()
                    .orElse(new DeviceInformationDO());
            if (ObjectUtil.isEmpty(deviceInformationDO.getDeviceNo())) {
                log.info("当前机器人查不到对应的充电桩类型、或者机器人不能在此区域充电 :{}", robot.getRobotNo());
                continue;
            }

            RobotChargeLogDO logDo = new RobotChargeLogDO();
            logDo.setRobotNo(robot.getRobotNo());
            logDo.setDeviceNo(deviceInformationDO.getDeviceNo());
            logDo.setPositionMapItemId(deviceInformationDO.getPositionMapItemId());


            logDo.setStartElectricity(electricity);
            //配置的充满电电量
            BigDecimal robotFullElectricity = new BigDecimal(znConfigConstant.getFullElectricity());
            //车子剩余电量
            BigDecimal robotRemainingElectricity = new BigDecimal(electricity + "");
            if (ObjectUtil.isNotEmpty(chargeConfig.getChanceCycle()) && !chargeFullNos.contains(robot.getRobotNo())
                    && robotRemainingElectricity.compareTo(robotFullElectricity) < 0) {
                //充满电
                logDo.setChargeModel(ChargeModelEnum.FULL.getType());
                Long taskDetailId = createChargeTask(robot.getRobotNo(), tasks, taskDetails, deviceInformationDO.getPositionMapItemId(), deviceInformationDO.getDeviceNo());
                logDo.setTaskDetailId(taskDetailId);
                logDo.setId(logDo.getTaskDetailId());
                logs.add(logDo);
                deviceInformationDOS.removeIf(v -> logDo.getDeviceNo().equals(v.getDeviceNo()));
                log.info("分配到充满电充电任务 :{} ,充电设备编号是 :{}, 任务id :{}", logDo.getRobotNo(), logDo.getDeviceNo(), logDo.getTaskDetailId());
                continue;
            }

            if (ObjectUtil.isNotEmpty(detailMap) && detailMap.containsKey(robot.getRobotNo())
                    && ObjectUtil.isNotEmpty(robot.getAutoCharge())) {
                //任务充电
                BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(robot.getAutoCharge()));
                if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
                    RobotTaskDetailDO robotTaskDetailDO = detailMap.get(robot.getRobotNo()).get(0);
                    deviceInformationDOS.removeIf(v -> logDo.getDeviceNo().equals(v.getDeviceNo()));
                    logDo.setChargeModel(ChargeModelEnum.TASK.getType());
                    logDo.setTaskDetailId(robotTaskDetailDO.getId());
                    logDo.setId(logDo.getTaskDetailId());
                    logs.add(logDo);
                    log.info("分配到任务充电任务 :{} ,充电设备编号是 :{}, 任务id :{}", logDo.getRobotNo(), logDo.getDeviceNo(), logDo.getTaskDetailId());
                    continue;
                }
            }

            if (ObjectUtil.isNotEmpty(detailMap) && detailMap.containsKey(robot.getRobotNo())
                    && ObjectUtil.isNotEmpty(chargeConfig.getStartAutoCharge())) {
                //任务充电
                BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(chargeConfig.getStartAutoCharge()));
                if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
                    RobotTaskDetailDO robotTaskDetailDO = detailMap.get(robot.getRobotNo()).get(0);
                    deviceInformationDOS.removeIf(v -> logDo.getDeviceNo().equals(v.getDeviceNo()));
                    logDo.setChargeModel(ChargeModelEnum.TASK.getType());
                    logDo.setTaskDetailId(robotTaskDetailDO.getId());
                    logDo.setId(logDo.getTaskDetailId());
                    logs.add(logDo);
                    log.info("分配到任务充电任务 :{} ,充电设备编号是 :{}, 任务id :{}", logDo.getRobotNo(), logDo.getDeviceNo(), logDo.getTaskDetailId());
                    continue;
                }
            }

            if (ObjectUtil.isNotEmpty(detailMap) && detailMap.containsKey(robot.getRobotNo())
                    && ObjectUtil.isNotEmpty(chargeConfig.getChanceChargeStart())) {
                //任务充电
                BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(chargeConfig.getChanceChargeStart()));
                if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
                    RobotTaskDetailDO robotTaskDetailDO = detailMap.get(robot.getRobotNo()).get(0);
                    deviceInformationDOS.removeIf(v -> logDo.getDeviceNo().equals(v.getDeviceNo()));
                    logDo.setChargeModel(ChargeModelEnum.TASK.getType());
                    logDo.setTaskDetailId(robotTaskDetailDO.getId());
                    logDo.setId(logDo.getTaskDetailId());
                    logs.add(logDo);
                    log.info("分配到任务充电任务 :{} ,充电设备编号是 :{}, 任务id :{}", logDo.getRobotNo(), logDo.getDeviceNo(), logDo.getTaskDetailId());
                    continue;
                }
            }

            if (ObjectUtil.isNotEmpty(robot.getAutoCharge())) {
                //自动充电
                BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(robot.getAutoCharge()));
                if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
                    logDo.setChargeModel(ChargeModelEnum.AUTO.getType());
                    Long taskDetailId = createChargeTask(robot.getRobotNo(), tasks, taskDetails, deviceInformationDO.getPositionMapItemId(), deviceInformationDO.getDeviceNo());
                    logDo.setTaskDetailId(taskDetailId);
                    logDo.setId(logDo.getTaskDetailId());
                    logs.add(logDo);
                    deviceInformationDOS.removeIf(v -> logDo.getDeviceNo().equals(v.getDeviceNo()));
                    log.info("分配到自动充电任务 :{} ,充电设备编号是 :{}", logDo.getRobotNo(), logDo.getDeviceNo());
                    continue;
                }
            }

            if (ObjectUtil.isNotEmpty(chargeConfig.getStartAutoCharge())) {
                //自动充电
                BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(chargeConfig.getStartAutoCharge()));
                if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
                    logDo.setChargeModel(ChargeModelEnum.AUTO.getType());
                    Long taskDetailId = createChargeTask(robot.getRobotNo(), tasks, taskDetails, deviceInformationDO.getPositionMapItemId(), deviceInformationDO.getDeviceNo());
                    logDo.setTaskDetailId(taskDetailId);
                    logDo.setId(logDo.getTaskDetailId());
                    logs.add(logDo);
                    deviceInformationDOS.removeIf(v -> logDo.getDeviceNo().equals(v.getDeviceNo()));
                    log.info("分配到自动充电任务 :{} ,充电设备编号是 :{}", logDo.getRobotNo(), logDo.getDeviceNo());
                    continue;
                }
            }

            if (ObjectUtil.isNotEmpty(chargeConfig.getChanceChargeStart())) {
                //机会充电
                BigDecimal robotConfigElectricity = new BigDecimal(String.valueOf(chargeConfig.getChanceChargeStart()));
                if (robotRemainingElectricity.compareTo(robotConfigElectricity) < 0) {
                    logDo.setChargeModel(ChargeModelEnum.CHANCE.getType());
                    Long taskDetailId = createChargeTask(robot.getRobotNo(), tasks, taskDetails, deviceInformationDO.getPositionMapItemId(), deviceInformationDO.getDeviceNo());
                    logDo.setTaskDetailId(taskDetailId);
                    logDo.setId(logDo.getTaskDetailId());
                    logs.add(logDo);
                    deviceInformationDOS.removeIf(v -> logDo.getDeviceNo().equals(v.getDeviceNo()));
                    log.info("分配到机会充电任务 :{} ,充电设备编号是 :{}", logDo.getRobotNo(), logDo.getDeviceNo());
                }
            }
        }
    }

    /**
     * 自动充电
     */
    public Long createChargeTask(String robotNo, List<RobotTaskDO> tasks, List<RobotTaskDetailAddVO> taskDetails, Long positionMapItemId, String deviceNo) {
        RobotTaskDO task = new RobotTaskDO();
        String incrementByKey = redisUtil.getIncrementByKey(RobotCacheLockEnum.TASK_NO.getKey());
        task.setTaskNo(znConfigConstant.getChargeNo() + DateUtils.getYearMonthDay() + incrementByKey);
        task.setId(IdUtil.getSnowflakeNextId());
        task.setCycleNumber(0L);
        task.setRemainingCycleNumber(0L);
        task.setStartTime(LocalDateTime.now());

        RobotTaskDetailAddVO detailAddVO = new RobotTaskDetailAddVO();
        detailAddVO.setId(IdUtil.getSnowflakeNextId());
        detailAddVO.setRobotTaskId(task.getId());
        detailAddVO.setTaskType(RobotTaskTypeEnum.CHARGE.getType());
        detailAddVO.setReleaseType(ReleaseTakeEnum.TO_LOCATION.getType());
        detailAddVO.setReleaseId(positionMapItemId);
        detailAddVO.setToLocationNo(deviceNo);
        detailAddVO.setRobotNo(robotNo);
        tasks.add(task);
        taskDetails.add(detailAddVO);
        return detailAddVO.getId();
    }

}
