
package com.cmvr.inspection.service.impl;

import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import cmvr.msgs.Agv;
import com.baomidou.mybatisplus.spring.service.impl.ServiceImpl;
import com.cmvr.common.utils.SecurityUtils;
import com.cmvr.device.domain.DeDeviceTerminalConfig;
import com.cmvr.device.service.IDeDeviceTerminalConfigService;
import com.cmvr.edge.client.model.EdgeCommonVO;
import com.cmvr.edge.client.service.EdgeAgvService;
import com.cmvr.inspection.domain.InspectionMap;
import com.cmvr.inspection.domain.vo.InspectionRobotVo;
import com.cmvr.inspection.mapper.InspectionMapMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cmvr.common.utils.DateUtils;
import com.cmvr.inspection.mapper.InspectionRobotMapper;
import com.cmvr.inspection.domain.InspectionRobot;
import com.cmvr.inspection.service.IInspectionRobotService;
import cn.hutool.core.util.StrUtil;
import com.cmvr.common.exception.GlobalException;

/**
 * 巡检机器人Service业务层处理
 *
 * @author cmvr-iot
 * @since 2026-05-29
 */
@Service
public class InspectionRobotServiceImpl extends ServiceImpl<InspectionRobotMapper, InspectionRobot> implements IInspectionRobotService
{
    @Autowired
    private InspectionRobotMapper inspectionRobotMapper;

    @Autowired
    private InspectionMapMapper inspectionMapMapper;

    @Autowired
    private EdgeAgvService edgeAgvService;

    @Autowired
    private IDeDeviceTerminalConfigService deDeviceTerminalConfigService;

    /**
     * 查询巡检机器人
     *
     * @param id 巡检机器人主键
     * @return 巡检机器人
     */
    @Override
    public InspectionRobot selectInspectionRobotById(String id)
    {
        return inspectionRobotMapper.selectInspectionRobotById(id);
    }

    /**
     * 查询巡检机器人列表
     *
     * @param inspectionRobot 巡检机器人
     * @return 巡检机器人
     */
    @Override
    public List<InspectionRobotVo> selectInspectionRobotList(InspectionRobot inspectionRobot)
    {
        return inspectionRobotMapper.selectInspectionRobotVoList(inspectionRobot);
    }

    /**
     * 新增巡检机器人
     *
     * @param inspectionRobot 巡检机器人
     * @return 结果
     */
    @Override
    public int insertInspectionRobot(InspectionRobot inspectionRobot)
    {
        DeDeviceTerminalConfig deDeviceTerminalConfig = new DeDeviceTerminalConfig();
        deDeviceTerminalConfig.setName(inspectionRobot.getRobotName());
        deDeviceTerminalConfig.setDescription("机器人终端");
        deDeviceTerminalConfig.setStatus("1");
        deDeviceTerminalConfig.setHost(inspectionRobot.getIpAddress());
        deDeviceTerminalConfig.setPort(inspectionRobot.getPort());
        // 自动创建设备管理模块的终端并将终端id保存机器人中
        deDeviceTerminalConfigService.insertDeDeviceTerminalConfig(deDeviceTerminalConfig);
        inspectionRobot.setTerminalId(deDeviceTerminalConfig.getId());
        // 生成UUID作为主键
        if (inspectionRobot.getId() == null || inspectionRobot.getId().isEmpty()) {
            inspectionRobot.setId(UUID.randomUUID().toString().replace("-", ""));
        }
        inspectionRobot.setCreateTime(DateUtils.getNowDate());
        inspectionRobot.setCreateBy(SecurityUtils.getUsername());
        return inspectionRobotMapper.insertInspectionRobot(inspectionRobot);
    }

    /**
     * 修改巡检机器人
     *
     * @param inspectionRobot 巡检机器人
     * @return 结果
     */
    @Override
    public int updateInspectionRobot(InspectionRobot inspectionRobot)
    {
        inspectionRobot.setUpdateTime(DateUtils.getNowDate());
        inspectionRobot.setUpdateBy(SecurityUtils.getUsername());
        DeDeviceTerminalConfig deDeviceTerminalConfig = deDeviceTerminalConfigService.selectDeDeviceTerminalConfigById(inspectionRobot.getTerminalId());
        deDeviceTerminalConfig.setName(inspectionRobot.getRobotName());
        deDeviceTerminalConfig.setHost(inspectionRobot.getIpAddress());
        deDeviceTerminalConfig.setPort(inspectionRobot.getPort());
        deDeviceTerminalConfigService.updateDeDeviceTerminalConfig(deDeviceTerminalConfig);
        return inspectionRobotMapper.updateInspectionRobot(inspectionRobot);
    }

    /**
     * 批量删除巡检机器人
     *
     * @param ids 需要删除的巡检机器人主键
     * @return 结果
     */
    @Override
    public int deleteInspectionRobotByIds(String[] ids)
    {
        List<InspectionRobot> inspectionRobots = inspectionRobotMapper.selectBatchIds(Arrays.asList(ids));
        deDeviceTerminalConfigService.deleteDeDeviceTerminalConfigByIds(inspectionRobots.stream().map(InspectionRobot::getTerminalId).toArray(String[]::new));
        return inspectionRobotMapper.deleteInspectionRobotByIds(ids);
    }

    /**
     * 获取机器人地图列表（从AGV获取）
     *
     * @param robotId 机器人ID
     * @return 地图列表
     */
    @Override
    public List<String> getRobotMapList(String robotId)
    {
        InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(robotId);
        if (robot == null) {
            throw new GlobalException("机器人不存在");
        }
        if (StrUtil.isBlank(robot.getIpAddress())) {
            throw new GlobalException("机器人IP地址未配置");
        }

        EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
        edgeCommonVO.setTerminalId(robot.getTerminalId());
        edgeCommonVO.setDeviceId(robot.getRobotCode());

        return edgeAgvService.listMaps(edgeCommonVO);
    }

    /**
     * 绑定机器人地图
     *
     * @param robotId 机器人ID
     * @param mapId 地图ID
     * @return 结果
     */
    @Override
    public int bindRobotMap(String robotId, String mapId)
    {
        InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(robotId);
        if (robot == null) {
            throw new GlobalException("机器人不存在");
        }

        InspectionMap map = inspectionMapMapper.selectInspectionMapById(mapId);
        if (map == null) {
            throw new GlobalException("地图不存在");
        }

        robot.setCurrentMapId(mapId);
        robot.setUpdateTime(DateUtils.getNowDate());
        robot.setUpdateBy(SecurityUtils.getUsername());

        return inspectionRobotMapper.updateInspectionRobot(robot);
    }

    /**
     * 从机器人下载地图
     *
     * @param robotId 机器人ID
     * @param mapName 地图名称
     * @return 地图内容
     */
    @Override
    public String downloadMapFromRobot(String robotId, String mapName)
    {
        InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(robotId);
        if (robot == null) {
            throw new GlobalException("机器人不存在");
        }

        EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
        edgeCommonVO.setTerminalId(robot.getTerminalId());
        edgeCommonVO.setDeviceId(robot.getRobotCode());

        return edgeAgvService.downloadMap(edgeCommonVO, mapName);
    }

    /**
     * 上传地图（从源机器人下载到目标机器人）
     *
     * @param robotId 目标机器人ID
     * @return 结果
     */
    @Override
    public String uploadMapFromSource(String robotId)
    {
        // 1. 获取目标机器人信息
        InspectionRobot targetRobot = inspectionRobotMapper.selectInspectionRobotById(robotId);
        if (targetRobot == null) {
            throw new GlobalException("目标机器人不存在");
        }

        // 2. 获取地图信息
        InspectionMap map = inspectionMapMapper.selectInspectionMapById(targetRobot.getCurrentMapId());
        if (map == null) {
            throw new GlobalException("地图不存在");
        }

        // 3. 检查地图是否有来源机器人ID和地图名称
        if (StrUtil.isBlank(map.getMapSourceRobotId())) {
            throw new GlobalException("地图未配置来源机器人ID");
        }
        if (StrUtil.isBlank(map.getMapSourceName())) {
            throw new GlobalException("地图未配置来源地图名称");
        }

        // 4. 获取来源机器人信息
        InspectionRobot sourceRobot = inspectionRobotMapper.selectInspectionRobotById(map.getMapSourceRobotId());
        if (sourceRobot == null) {
            throw new GlobalException("来源机器人不存在");
        }

        // 5. 从来源机器人下载地图JSON
        EdgeCommonVO sourceEdgeVO = new EdgeCommonVO();
        sourceEdgeVO.setTerminalId(sourceRobot.getTerminalId());
        sourceEdgeVO.setDeviceId(sourceRobot.getRobotCode());

        String mapContent = edgeAgvService.downloadMap(sourceEdgeVO, map.getMapSourceName());

        if (StrUtil.isBlank(mapContent)) {
            throw new GlobalException("下载的地图内容为空");
        }

        // 6. 上传地图到目标机器人
        EdgeCommonVO targetEdgeVO = new EdgeCommonVO();
        targetEdgeVO.setTerminalId(targetRobot.getTerminalId());
        targetEdgeVO.setDeviceId(targetRobot.getRobotCode());

        edgeAgvService.uploadMap(targetEdgeVO, map.getMapSourceName(), mapContent);

        return "上传成功";
    }

    /**
     * 同步机器人状态（电量、位置等）
     *
     * @param robotId 机器人ID
     * @return 更新后的机器人信息
     */
    @Override
    public InspectionRobot syncRobotStatus(String robotId)
    {
        InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(robotId);
        if (robot == null) {
            throw new GlobalException("机器人不存在");
        }

        EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
        edgeCommonVO.setTerminalId(robot.getTerminalId());
        edgeCommonVO.setDeviceId(robot.getRobotCode());

        try {
            // 获取运行时状态（包含电池、位置等信息）
            Agv.AgvRuntimeState runtimeState = edgeAgvService.getRuntimeState(edgeCommonVO);
            
            // 设置电池电量
            if (runtimeState.hasBattery()) {
                robot.setBatteryLevel((int)(runtimeState.getBattery().getPercentage() * 100));
            }

            // 设置位置信息
            if (runtimeState.hasPose()) {
                Agv.AgvPose2d pose = runtimeState.getPose();
                robot.setCurrentPosition(pose.getX() + "," + pose.getY() + "," + pose.getTheta());
            }

            robot.setUpdateTime(DateUtils.getNowDate());
            inspectionRobotMapper.updateInspectionRobot(robot);

        } catch (Exception e) {
            // 记录日志但不抛出异常，允许部分失败
            e.printStackTrace();
        }

        return robot;
    }

    /**
     * 获取机器人实时位置
     *
     * @param robotId 机器人ID
     * @return 机器人位置信息
     */
    @Override
    public Agv.AgvPose2d getRobotRealtimeLocation(String robotId)
    {
        InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(robotId);
        if (robot == null) {
            throw new GlobalException("机器人不存在");
        }

        EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
        edgeCommonVO.setTerminalId(robot.getTerminalId());
        edgeCommonVO.setDeviceId(robot.getRobotCode());

        Agv.AgvRuntimeState runtimeState = edgeAgvService.getRuntimeState(edgeCommonVO);
        return runtimeState.hasPose() ? runtimeState.getPose() : null;
    }

    /**
     * 导航到指定位置（坐标）
     *
     * @param robotId 机器人ID
     * @param x X坐标（米）
     * @param y Y坐标（米）
     * @param theta 朝向角（弧度）
     */
    @Override
    public void navigateToPosition(String robotId, Double x, Double y, Double theta)
    {
        InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(robotId);
        if (robot == null) {
            throw new GlobalException("机器人不存在");
        }

        if (x == null || y == null) {
            throw new GlobalException("X和Y坐标不能为空");
        }

        // 构建目标位姿
        Agv.AgvPose2d pose = Agv.AgvPose2d.newBuilder()
            .setX(x)
            .setY(y)
            .setTheta(theta != null ? theta : 0.0)
            .build();

        EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
        edgeCommonVO.setTerminalId(robot.getTerminalId());
        edgeCommonVO.setDeviceId(robot.getRobotCode());

        // 调用边缘端接口进行导航
        edgeAgvService.navigateToPose(edgeCommonVO, pose);
    }

    /**
     * 开始建图
     *
     * @param robotId 机器人ID
     * @param dimension 建图维度（0:未指定 1:2D 2:3D 3:2D+3D）
     * @param mapName 地图名称（可选）
     * @param realTime 是否实时建图
     * @return 会话ID
     */
    @Override
    public String startMapping(String robotId, int dimension, String mapName, boolean realTime)
    {
        InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(robotId);
        if (robot == null) {
            throw new GlobalException("机器人不存在");
        }

        EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
        edgeCommonVO.setTerminalId(robot.getTerminalId());
        edgeCommonVO.setDeviceId(robot.getRobotCode());

        Agv.AgvMapDimension mapDimension = Agv.AgvMapDimension.forNumber(dimension);
        return edgeAgvService.startMapping(edgeCommonVO, mapDimension, mapName, realTime);
    }

    /**
     * 停止建图
     *
     * @param robotId 机器人ID
     */
    @Override
    public void stopMapping(String robotId)
    {
        InspectionRobot robot = inspectionRobotMapper.selectInspectionRobotById(robotId);
        if (robot == null) {
            throw new GlobalException("机器人不存在");
        }

        EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
        edgeCommonVO.setTerminalId(robot.getTerminalId());
        edgeCommonVO.setDeviceId(robot.getRobotCode());

        edgeAgvService.stopMapping(edgeCommonVO);
    }

}