package cn.iocoder.yudao.module.system.api.robot;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
import cn.iocoder.yudao.module.system.api.robot.dto.*;
import cn.iocoder.yudao.module.system.api.robot.processor.RequestProcessor;
import cn.iocoder.yudao.module.system.api.robot.websocket.RobotInformationVO;
import cn.iocoder.yudao.module.system.api.robot.vo.RobotReactiveStatusDTO;
import cn.iocoder.yudao.module.system.api.robot.websocket.RobotStatusDataPoseDTO;
import cn.iocoder.yudao.module.system.config.mqtt.util.MqttUtils;
import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant;
import cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter;
import cn.iocoder.yudao.module.system.constant.CommonConstant;
import cn.iocoder.yudao.module.system.constant.area.FloorAreaConstant;
import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
@RestController // 提供 RESTful API 接口，给 Feign 调用
@Validated
public class RobotStatusApiImpl implements RobotStatusApi {

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private RobotInformationService robotInformationService;

    @Autowired
    private ZnConfigConstant znConfigConstant;

    @Resource
    private RequestProcessor processor;

    private static final ExecutorService executorService = Executors.newFixedThreadPool(50);

    /*@Resource
    private CommonApi commonApi;*/

    @Autowired
    private MqttUtils mqttUtils;

    /**
     * 更新机器人点位/异常/能否做任务
     *
     * @param robotStatusDataDTO
     * @return
     */
    @Override
    @SystemRateLimiter(time = 1, count = 150, keyArg = "robotStatusUpdate", message = "机器人上报点位超过限流")
    public void robotStatusUpdate(RobotPoseStatusDTO robotStatusDataDTO) {
        executorService.execute(() -> {
            updateRobotPosed(robotStatusDataDTO);
        });
    }

    /**
     * 更新点位信息
     *
     * @param robotStatusDataDTO
     */
    private void updateRobotPosed(RobotPoseStatusDTO robotStatusDataDTO) {
        TenantContextHolder.setTenantId(1L);
        if (ObjectUtil.isEmpty(robotStatusDataDTO) || ObjectUtil.isEmpty(robotStatusDataDTO.getMac())) {
            log.info("机器人上报的信息不全 :{}", JSON.toJSONString(robotStatusDataDTO));
            return;
        }
        String floorAreaKey = RobotTaskChcheConstant.ROBOT_FLOOR_AREA + robotStatusDataDTO.getMac();
        Object floorAreaObject = redisUtil.get(floorAreaKey);
        FloorZoneDTO floorZoneDTO = JSONUtil.toBean((String) floorAreaObject, FloorZoneDTO.class);
        String robotNo = robotInformationService.getRobotNoByMac(robotStatusDataDTO.getMac());
        String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT + robotStatusDataDTO.getMac();
        Object object = redisUtil.get(pose2dKey);
        RobotStatusDataPoseDTO robotStatusDataPoseDTO = JSONUtil.toBean((String) object, RobotStatusDataPoseDTO.class);

        if (ObjectUtil.isNotEmpty(robotStatusDataDTO.getPose2d())) {
            robotStatusDataPoseDTO.setX(robotStatusDataDTO.getPose2d().getX());
            robotStatusDataPoseDTO.setY(robotStatusDataDTO.getPose2d().getY());
            if (robotStatusDataDTO.getPose2d().getYaw().length()>7) {
                String yaw = robotStatusDataDTO.getPose2d().getYaw().substring(0, 7);
                robotStatusDataPoseDTO.setYaw(yaw);
            }else {
                robotStatusDataPoseDTO.setYaw(robotStatusDataDTO.getPose2d().getYaw());
            }

        }
        robotStatusDataPoseDTO.setRobotNo(robotNo);
        robotStatusDataPoseDTO.setFloor(floorZoneDTO.getFloor());
        robotStatusDataPoseDTO.setArea(floorZoneDTO.getArea());

        String speedKey = RobotTaskChcheConstant.ROBOT_SPEED_FORK_HEIGHT + robotNo;
        Object speedObject = redisUtil.get(speedKey);
        if (ObjectUtil.isNotEmpty(speedObject)) {
            RobotReactiveStatusDTO data = JSON.parseObject(speedObject.toString(), RobotReactiveStatusDTO.class);
            robotStatusDataPoseDTO.setForkHeight(data.getForkHeight());
        }

        redisUtil.set(pose2dKey, JSON.toJSONString(robotStatusDataPoseDTO), znConfigConstant.getRobotPositionCacheTime());

        robotStatusDataPoseDTO.setTimestamp(robotStatusDataDTO.getTimestamp());
        sendToPP(robotStatusDataPoseDTO);

        // -- 通过mac 地址获取车辆信息 - (并且加入到缓存中)
        Map<String, RobotInformationVO> robotInformationVOS = robotInformationService.getAllRobotByRedis();
        RobotInformationVO robotInformationVO = robotInformationVOS.get(robotStatusDataDTO.getMac());
        if (robotInformationVO == null) {
            robotInformationVO = robotInformationService.getRobotByRedis(robotStatusDataDTO.getMac());
        }
        robotInformationVO.setPose2d(robotStatusDataPoseDTO);

        RobotInformationVO finalRobotInformationVO = robotInformationVO;

        String floorArea = floorZoneDTO.getFloor() + CommonConstant.SYMBOL + floorZoneDTO.getArea();
        executorService.execute(() ->{
            //机器人身上是否有货
            String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robotStatusDataDTO.getMac();
            String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED + robotStatusDataDTO.getMac();
            redisUtil.set(taskStatusKey, robotStatusDataDTO.getTaskStatus(), znConfigConstant.getRobotPositionCacheTime());
            redisUtil.set(cargoDetectedKey, robotStatusDataDTO.getCargoDetected(), znConfigConstant.getRobotPositionCacheTime());
            Map<String, Object> map = new HashMap<>();
            String value = FloorAreaConstant.FLOOR_AREA_ROBOT +floorArea;
            map.put(robotStatusDataDTO.getMac(), JSON.toJSONString(finalRobotInformationVO));
            redisUtil.hmset(value, map, 5);
        });

       /* executorService.execute(() ->{
            // 合并请求 - 这里接受到的数据都丢给 RequestProcessor - 再整合数据通过WebSocket丢给前端
            processor.handleRequest(floorArea,robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(finalRobotInformationVO));
        });*/

    }

    private void sendToPP(RobotStatusDataPoseDTO robotStatusDataPoseDTO) {
//        commonApi.commonMethod(robotStatusDataPoseDTO, PathPlanningTopicConstant.AGV_POSE);
        mqttUtils.pub(PathPlanningTopicConstant.AGV_POSE,JSON.toJSONString(robotStatusDataPoseDTO));
    }
}
