package tech.easyflow.agent.distributed;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import tech.easyflow.agent.config.AgentRuntimeProperties;
import tech.easyflow.agent.runtime.AgentRunService;
import tech.easyflow.common.mq.config.MQProperties;
import tech.easyflow.common.mq.core.MQConsumerHandler;
import tech.easyflow.common.mq.core.MQMessage;
import tech.easyflow.common.mq.core.MQSubscription;

import java.util.List;

/**
 * Agent 运行态远程命令消费者。
 */
@Component
public class AgentRuntimeCommandConsumer implements MQConsumerHandler {

    private static final Logger LOG = LoggerFactory.getLogger(AgentRuntimeCommandConsumer.class);

    private final ObjectMapper objectMapper;
    private final AgentRuntimeProperties properties;
    private final MQProperties mqProperties;
    private final AgentRunService agentRunService;
    private final AgentRuntimeCommandResultRegistry resultRegistry;

    /**
     * 创建 Agent 运行态远程命令消费者。
     *
     * @param objectMapper JSON 序列化器
     * @param properties Agent 运行配置
     * @param mqProperties MQ 配置
     * @param agentRunService Agent 运行服务
     * @param resultRegistry 远程命令结果注册表
     */
    public AgentRuntimeCommandConsumer(ObjectMapper objectMapper,
                                       AgentRuntimeProperties properties,
                                       MQProperties mqProperties,
                                       AgentRunService agentRunService,
                                       AgentRuntimeCommandResultRegistry resultRegistry) {
        this.objectMapper = objectMapper;
        this.properties = properties;
        this.mqProperties = mqProperties;
        this.agentRunService = agentRunService;
        this.resultRegistry = resultRegistry;
    }

    @Override
    public MQSubscription subscription() {
        MQSubscription subscription = new MQSubscription();
        subscription.setTopic(commandTopic());
        subscription.setConsumerGroup(commandTopic());
        subscription.setShardCount(Math.max(mqProperties.getRedis().getChatPersistShardCount(), 1));
        subscription.setBatchEnabled(false);
        return subscription;
    }

    @Override
    public void handle(List<MQMessage> messages) {
        if (messages == null || messages.isEmpty()) {
            return;
        }
        for (MQMessage message : messages) {
            try {
                handleCommand(message, objectMapper.readValue(message.getBody(), AgentRuntimeCommandMessage.class));
            } catch (Exception e) {
                LOG.warn("Agent 远程运行命令解析失败: messageId={}", message.getMessageId(), e);
            }
        }
    }

    private void handleCommand(MQMessage message, AgentRuntimeCommandMessage command) {
        if (command == null || command.getAction() == null) {
            LOG.warn("跳过非法 Agent 远程运行命令: messageId={}", message.getMessageId());
            return;
        }
        if (!properties.getInstanceId().equals(command.getTargetNodeId())) {
            LOG.warn("跳过非本节点 Agent 远程运行命令: messageId={}, targetNodeId={}, currentNodeId={}",
                    message.getMessageId(), command.getTargetNodeId(), properties.getInstanceId());
            return;
        }
        try {
            if (command.getAction() == AgentRuntimeCommandAction.APPROVE) {
                agentRunService.approveRuntimeLocal(
                        command.getRequestId(), command.getResumeToken(), command.getOperatorId(), command.getUserId());
            } else if (command.getAction() == AgentRuntimeCommandAction.REJECT) {
                agentRunService.rejectRuntimeLocal(
                        command.getRequestId(), command.getResumeToken(), command.getReason(),
                        command.getOperatorId(), command.getUserId());
            } else {
                markFailureQuietly(command, new IllegalArgumentException("不支持的 Agent 远程运行命令"));
                LOG.warn("跳过不支持的 Agent 远程运行命令: messageId={}, commandId={}, action={}",
                        message.getMessageId(), command.getCommandId(), command.getAction());
                return;
            }
        } catch (RuntimeException e) {
            markFailureQuietly(command, e);
            LOG.warn("Agent 远程运行命令处理失败: messageId={}, commandId={}",
                    message.getMessageId(), command.getCommandId(), e);
            return;
        }
        markSuccessQuietly(command);
    }

    private String commandTopic() {
        return properties.getCommandTopicPrefix() + ":" + properties.getInstanceId();
    }

    private void markSuccessQuietly(AgentRuntimeCommandMessage command) {
        try {
            resultRegistry.markSuccess(command.getCommandId());
        } catch (RuntimeException e) {
            LOG.error("Agent 远程运行命令成功结果写入失败: commandId={}", command.getCommandId(), e);
        }
    }

    private void markFailureQuietly(AgentRuntimeCommandMessage command, RuntimeException cause) {
        try {
            resultRegistry.markFailure(command.getCommandId(), cause.getMessage());
        } catch (RuntimeException e) {
            LOG.error("Agent 远程运行命令失败结果写入失败: commandId={}", command.getCommandId(), e);
        }
    }
}
