package cn.iocoder.yudao.module.system.service.remote;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotMaxSpeedDTO;
import cn.iocoder.yudao.module.system.api.robot.dto.FloorZoneDTO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RobotMaxSpeedPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RobotMaxSpeedSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
import cn.iocoder.yudao.module.system.dal.dataobject.remote.RobotMaxSpeedDO;
import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapMapper;
import cn.iocoder.yudao.module.system.dal.mysql.remote.RobotMaxSpeedMapper;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.ROBOT_MAX_SPEED_NOT_EXISTS;

/**
 * 远遥车辆最大速度 Service 实现类
 *
 * @author 陈宾顺
 */
@Service
@Validated
public class RobotMaxSpeedServiceImpl extends ServiceImpl<RobotMaxSpeedMapper, RobotMaxSpeedDO> implements RobotMaxSpeedService {

    @Resource
    private RobotMaxSpeedMapper robotMaxSpeedMapper;

    @Resource
    private RobotInformationService informationService;

    @Resource
    private PositionMapMapper positionMapMapper;

    @Override
    public Long createRobotMaxSpeed(RobotMaxSpeedSaveReqVO createReqVO) {
        // 插入
        RobotMaxSpeedDO robotMaxSpeed = BeanUtils.toBean(createReqVO, RobotMaxSpeedDO.class);
        robotMaxSpeedMapper.insert(robotMaxSpeed);
        // 返回
        return robotMaxSpeed.getId();
    }

    @Override
    public void updateRobotMaxSpeed(RobotMaxSpeedSaveReqVO updateReqVO) {
        // 校验存在
        validateRobotMaxSpeedExists(updateReqVO.getId());
        // 更新
        RobotMaxSpeedDO updateObj = BeanUtils.toBean(updateReqVO, RobotMaxSpeedDO.class);
        robotMaxSpeedMapper.updateById(updateObj);
    }

    @Override
    public void deleteRobotMaxSpeed(Long id) {
        // 校验存在
        validateRobotMaxSpeedExists(id);
        // 删除
        robotMaxSpeedMapper.deleteById(id);
    }

    private void validateRobotMaxSpeedExists(Long id) {
        if (robotMaxSpeedMapper.selectById(id) == null) {
            throw exception(ROBOT_MAX_SPEED_NOT_EXISTS);
        }
    }

    @Override
    public RobotMaxSpeedDO getRobotMaxSpeed(Long id) {
        return robotMaxSpeedMapper.selectById(id);
    }

    @Override
    public PageResult<RobotMaxSpeedDO> getRobotMaxSpeedPage(RobotMaxSpeedPageReqVO pageReqVO) {
        return robotMaxSpeedMapper.selectPage(pageReqVO);
    }

    /**
     * 更新车辆编号
     *
     * @param oldRobotNo
     * @param newRobotNo
     */
    @Override
    public void updateRobotNo(String oldRobotNo, String newRobotNo) {
        robotMaxSpeedMapper.updateRobotNo(oldRobotNo, newRobotNo);
    }

    @Override
    public void deleteByRobotNo(String robotNo) {
        robotMaxSpeedMapper.deleteByRobotNo(robotNo);
    }

    @Override
    public List<RemoteRobotMaxSpeedDTO> getAllRobotMaxSpeedList() {

        List<PositionMapDO> positionMaps = positionMapMapper.selectList(new LambdaQueryWrapperX<PositionMapDO>());
        if (ObjectUtil.isEmpty(positionMaps)) {
            return new ArrayList<>();
        }

        List<Long> mapIds = positionMaps.stream().map(PositionMapDO::getId).collect(Collectors.toList());

        List<RobotMaxSpeedDO> speedList = robotMaxSpeedMapper.selectList(new LambdaQueryWrapper<RobotMaxSpeedDO>());

        List<RobotMaxSpeedDO> maxSpeeds = new ArrayList<>();
        if (ObjectUtil.isEmpty(speedList)) {
            for (PositionMapDO positionMap : positionMaps) {
                RobotMaxSpeedDO remoteRobotMaxSpeed = new RobotMaxSpeedDO();
                remoteRobotMaxSpeed.setPositionMapId(positionMap.getId());
                maxSpeeds.add(remoteRobotMaxSpeed);
            }
        } else {
            List<Long> positionMapIds = speedList.stream().map(RobotMaxSpeedDO::getPositionMapId).collect(Collectors.toList());
            List<Long> needAddMapIds = mapIds.stream().filter(v -> !positionMapIds.contains(v)).collect(Collectors.toList());
            if (ObjectUtil.isNotEmpty(needAddMapIds)) {
                for (Long mapId : needAddMapIds) {
                    RobotMaxSpeedDO remoteRobotMaxSpeed = new RobotMaxSpeedDO();
                    remoteRobotMaxSpeed.setPositionMapId(mapId);
                    maxSpeeds.add(remoteRobotMaxSpeed);
                }
            }
        }

        if (ObjectUtil.isNotEmpty(maxSpeeds)) {
            robotMaxSpeedMapper.insertBatch(maxSpeeds);
        }

        List<RobotMaxSpeedDO> allSpeedList = robotMaxSpeedMapper.selectList(new LambdaQueryWrapper<RobotMaxSpeedDO>());

        List<RemoteRobotMaxSpeedDTO> beans = BeanUtils.toBean(allSpeedList, RemoteRobotMaxSpeedDTO.class);

        Map<Long, PositionMapDO> positionMap =
                positionMaps.stream().collect(Collectors.toMap(v -> v.getId(), Function.identity()));

        for (RemoteRobotMaxSpeedDTO bean : beans) {
            PositionMapDO positionMapDO = positionMap.get(bean.getPositionMapId());
            bean.setArea(positionMapDO.getArea());
            bean.setFloor(positionMapDO.getFloor());
        }

        return beans;
    }

    @Override
    public void updateRobotMaxSpeedList(List<RemoteRobotMaxSpeedDTO> list) {
        List<RobotMaxSpeedDO> bean = BeanUtils.toBean(list, RobotMaxSpeedDO.class);
        robotMaxSpeedMapper.updateById(bean);
    }

    @Override
    public String getRobotMaxSpeedByRobotNo(String robotNo) {
        FloorZoneDTO floorZoneDTO = informationService.getFloorZoneDTOByRobotNo(robotNo);
        if (ObjectUtil.isEmpty(floorZoneDTO)) {
            return null;
        }

        PositionMapDO positionMap = positionMapMapper.selectOne(new LambdaQueryWrapperX<PositionMapDO>()
                .eq(PositionMapDO::getFloor, floorZoneDTO.getFloor())
                .eq(PositionMapDO::getArea, floorZoneDTO.getArea()));
        RobotMaxSpeedDO robotMaxSpeed = getRobotMaxSpeed(positionMap.getId());
        if (ObjectUtil.isEmpty(robotMaxSpeed)) {
            return null;
        }

        return robotMaxSpeed.getMaxSpeed();
    }

}
