package com.cmvr.edge.client.service.impl;

import cmvr.api.AgvCommand;
import cmvr.api.AgvServiceGrpc;
import cn.hutool.core.util.StrUtil;
import com.cmvr.common.exception.GlobalException;
import com.cmvr.edge.client.manage.GrpcServiceManager;
import com.cmvr.edge.client.model.EdgeCommonVO;
import com.cmvr.edge.client.service.EdgeAgvService;
import com.cmvr.edge.client.utils.EdgeCommonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * AGV服务实现类
 * 
 * @author cmvr-iot
 * @since 2026-06-11
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EdgeAgvServiceImpl implements EdgeAgvService {

    private final GrpcServiceManager grpcServiceManager;

    @Override
    public AgvCommand.AgvStatusInfo getStatusInfo(EdgeCommonVO edgeCommonVO) {
        AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
            edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
        AgvCommand.GetAgvStatusInfoCommand.Request request = AgvCommand.GetAgvStatusInfoCommand.Request.newBuilder()
            .setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
            .build();
        return executeGrpcCall(() -> stub.getStatusInfo(request)).getStatus();
    }


    @Override
    public AgvCommand.AgvRobotLocation getRobotLocation(EdgeCommonVO edgeCommonVO) {
        AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
            edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
        AgvCommand.RobotStatusLocCommand.Request request = AgvCommand.RobotStatusLocCommand.Request.newBuilder()
            .setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
            .build();
        return executeGrpcCall(() -> stub.getRobotLocation(request)).getStatus();
    }

    @Override
    public AgvCommand.AgvMapStatus getMapStatus(EdgeCommonVO edgeCommonVO) {
        AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
            edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
        AgvCommand.RobotStatusMapCommand.Request request = AgvCommand.RobotStatusMapCommand.Request.newBuilder()
            .setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
            .build();
        return executeGrpcCall(() -> stub.getMapStatus(request)).getStatus();
    }

    @Override
    public AgvCommand.AgvDownloadMapResult robotConfigDownloadMap(EdgeCommonVO edgeCommonVO, String mapName) {
        if (StrUtil.isBlank(mapName)) {
            throw new GlobalException("地图名称不能为空");
        }
        AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
            edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
        AgvCommand.RobotConfigDownloadMapRequestData requestData = AgvCommand.RobotConfigDownloadMapRequestData.newBuilder()
            .setMapName(mapName)
            .build();
        AgvCommand.RobotConfigDownloadMapCommand.Request request = AgvCommand.RobotConfigDownloadMapCommand.Request.newBuilder()
            .setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
            .setData(requestData)
            .build();
        AgvCommand.AgvDownloadMapResult result = executeGrpcCall(() -> stub.robotConfigDownloadMap(request)).getStatus();
        
        if (result.getRetCode() != 0) {
            throw new GlobalException("下载地图失败: " + result.getErrMsg());
        }
        return result;
    }

    @Override
    public AgvCommand.AgvBatteryStatus getBatteryStatus(EdgeCommonVO edgeCommonVO) {
        AgvServiceGrpc.AgvServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
            edgeCommonVO.getTerminalId(), AgvServiceGrpc.AgvServiceBlockingStub.class);
        AgvCommand.RobotStatusBatteryRequestData requestData = AgvCommand.RobotStatusBatteryRequestData.newBuilder()
                .setSimple(true)
                .build();
        AgvCommand.RobotStatusBatteryCommand.Request request = AgvCommand.RobotStatusBatteryCommand.Request.newBuilder()
            .setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
                .setData(requestData)
            .build();
        return executeGrpcCall(() -> stub.getBatteryStatus(request)).getStatus();
    }

    /**
     * 执行gRPC调用并处理异常
     *
     * @param call gRPC调用
     * @param <T> 返回类型
     * @return 调用结果
     */
    private <T> T executeGrpcCall(java.util.function.Supplier<T> call) {
        try {
            return call.get();
        } catch (Exception e) {
            log.error("AGV gRPC调用失败", e);
            throw new GlobalException("AGV通信失败: " + e.getMessage());
        }
    }
}
