package com.yupi.project.mqtt.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yupi.project.model.entity.RobotTask;
import com.yupi.project.model.enums.CommandTypeEnum;
import com.yupi.project.model.enums.RobotTaskStatusEnum;
import com.yupi.project.model.enums.ChargingSessionStatusEnum;
import com.yupi.project.service.ChargingSessionService;
import com.yupi.project.service.RobotTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

@Component
@Slf4j
public class MqttMessageHandlerImpl implements MqttMessageHandler {

    @Resource
    private RobotTaskService robotTaskService;

    @Resource
    private ChargingSessionService chargingSessionService;

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void handleStatusUpdate(String topic, String payload) {
        log.info("收到MQTT状态消息 - Topic: {}, Payload: {}", topic, payload);
        try {
            // 1. 解析Payload
            Map<String, Object> payloadMap = objectMapper.readValue(payload, Map.class);
            String robotUid = extractRobotUidFromTopic(topic);
            String commandTypeStr = (String) payloadMap.get("command_ack");
            CommandTypeEnum commandType = CommandTypeEnum.fromAck(commandTypeStr);
            Long originalTaskId = ((Number) payloadMap.get("task_id")).longValue();
            boolean success = (Boolean) payloadMap.getOrDefault("success", false);
            String message = (String) payloadMap.getOrDefault("message", "");

            if (robotUid == null || commandType == null || originalTaskId == null) {
                log.error("MQTT状态消息解析失败：robotUid, commandType,或taskId为空. Topic: {}, Payload: {}", topic, payload);
                return;
            }

            // 2. 更新RobotTask状态
            RobotTask task = robotTaskService.getById(originalTaskId);
            if (task == null) {
                log.warn("未找到与MQTT消息关联的机器人任务: taskId={}, robotUid={}", originalTaskId, robotUid);
                return;
            }
            if (!RobotTaskStatusEnum.SENT.getValue().equals(task.getStatus())){
                log.warn("任务 {} 状态为 {}, 非SENT状态，不再处理ACK消息。", originalTaskId, task.getStatus());
                return;
            }
            robotTaskService.markTaskAsAcknowledged(originalTaskId, success, success ? null : message, new Date());
            log.info("机器人任务 {} (robotUid: {}) 已确认为: {}, 消息: '{}'", originalTaskId, robotUid, success ? "成功" : "失败", message);

            // 3. 如果任务成功，则根据任务类型更新 ChargingSession
            if (success) {
                Long sessionId = task.getRelatedSessionId();
                if (sessionId == null) {
                    log.warn("机器人任务 {} 成功，但未关联充电会话ID，不处理会话状态更新。", originalTaskId);
                    return;
                }

                switch (commandType) {
                    case MOVE_TO_SPOT:
                        log.info("机器人 {} 到达车位指令已确认 (任务ID: {}), 更新会话 {} 状态。", robotUid, originalTaskId, sessionId);
                        chargingSessionService.handleRobotArrival(sessionId, originalTaskId);
                        break;
                    case START_CHARGE:
                        log.info("机器人 {} 开始充电指令已确认 (任务ID: {}), 更新会话 {} 状态。", robotUid, originalTaskId, sessionId);
                        chargingSessionService.handleChargingStart(sessionId, originalTaskId);
                        break;
                    case STOP_CHARGE:
                        BigDecimal energyConsumed = payloadMap.containsKey("energy_kwh") ? new BigDecimal(payloadMap.get("energy_kwh").toString()) : BigDecimal.ZERO;
                        int durationSeconds = payloadMap.containsKey("duration_s") ? ((Number) payloadMap.get("duration_s")).intValue() : 0;
                        log.info("机器人 {} 停止充电指令已确认 (任务ID: {}), 更新会话 {} 状态。电量: {}kWh, 时长: {}s", 
                                robotUid, originalTaskId, sessionId, energyConsumed, durationSeconds);
                        chargingSessionService.handleChargingEnd(sessionId, originalTaskId, energyConsumed, durationSeconds);
                        break;
                    default:
                        log.info("收到机器人任务 {} (类型:{}) 的ACK，但此类型不直接更新充电会话。", originalTaskId, commandType);
                        break;
                }
            } else {
                Long sessionId = task.getRelatedSessionId();
                if (sessionId != null) {
                    log.warn("机器人任务 {} (类型:{}) 失败，将关联的会话 {} 标记为错误。错误: {}", originalTaskId, commandType, sessionId, message);
                    chargingSessionService.cancelChargingSession(sessionId, null, 
                        "机器人任务失败: " + commandType + " - " + message, 
                        ChargingSessionStatusEnum.ERROR);
                }
            }

        } catch (Exception e) {
            log.error("处理MQTT状态消息时发生错误 - Topic: {}, Payload: {}", topic, payload, e);
        }
    }

    private String extractRobotUidFromTopic(String topic) {
        String[] parts = topic.split("/");
        if (parts.length > 0) {
            return parts[parts.length - 1];
        }
        return null;
    }
} 