package tech.easyflow.ai.easyagents.memory;

import com.easyagents.core.message.AiMessage;
import com.easyagents.core.message.Message;
import com.easyagents.core.message.ToolCall;
import com.easyagents.core.message.ToolMessage;
import tech.easyflow.core.runtime.ChatRuntimeHistoryPayloadHelper;
import tech.easyflow.core.runtime.ChatRuntimeMessage;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 负责把聊天运行时持久化 payload 恢复为 easy-agents 消息链。
 */
public final class ChatRuntimeHistoryMessageMapper {

    private ChatRuntimeHistoryMessageMapper() {
    }

    /**
     * 从运行时消息中恢复 assistant / tool 历史消息链。
     *
     * @param runtimeMessage 运行时消息
     * @return 恢复后的消息列表
     */
    public static List<Message> toStructuredMessages(ChatRuntimeMessage runtimeMessage) {
        if (runtimeMessage == null) {
            return Collections.emptyList();
        }
        Map<String, Object> payload = runtimeMessage.getContentPayload();
        List<Map<String, Object>> messageChain = ChatRuntimeHistoryPayloadHelper.getMessageChain(payload);
        if (!messageChain.isEmpty()) {
            return toMessages(messageChain);
        }
        if (!ChatRuntimeHistoryPayloadHelper.hasStructuredHistory(payload)) {
            return Collections.emptyList();
        }
        List<Message> messages = new ArrayList<>();
        Map<String, Object> assistantMessage = ChatRuntimeHistoryPayloadHelper.getAssistantMessage(payload);
        if (!assistantMessage.isEmpty()) {
            AiMessage aiMessage = toAiMessage(assistantMessage);
            if (aiMessage != null) {
                messages.add(aiMessage);
            }
        }
        List<Map<String, Object>> toolMessages = ChatRuntimeHistoryPayloadHelper.getToolMessages(payload);
        messages.addAll(toMessages(toolMessages));
        Map<String, Object> finalAssistantMessage = ChatRuntimeHistoryPayloadHelper.getFinalAssistantMessage(payload);
        if (!finalAssistantMessage.isEmpty()) {
            AiMessage finalAiMessage = toAiMessage(finalAssistantMessage);
            if (finalAiMessage != null) {
                messages.add(finalAiMessage);
            }
        } else if (!messages.isEmpty()
                && (runtimeMessage.getContentText() != null && !runtimeMessage.getContentText().isBlank())
                && assistantMessage.containsKey("toolCalls")) {
            messages.add(new AiMessage(runtimeMessage.getContentText()));
        }
        return messages;
    }

    private static List<Message> toMessages(List<Map<String, Object>> messageChain) {
        List<Message> messages = new ArrayList<>();
        for (Map<String, Object> item : messageChain) {
            String role = String.valueOf(item.get("role"));
            if ("assistant".equalsIgnoreCase(role)) {
                AiMessage aiMessage = toAiMessage(item);
                if (aiMessage != null) {
                    messages.add(aiMessage);
                }
            } else if ("tool".equalsIgnoreCase(role)) {
                ToolMessage toolMessage = toToolMessage(item);
                if (toolMessage != null) {
                    messages.add(toolMessage);
                }
            }
        }
        return messages;
    }

    private static AiMessage toAiMessage(Map<String, Object> item) {
        if (item == null || item.isEmpty()) {
            return null;
        }
        String content = stringValue(item.get("content"));
        String reasoningContent = stringValue(firstNonNull(item.get("reasoningContent"), item.get("reasoning_content")));
        List<ToolCall> toolCalls = toToolCalls(ChatRuntimeHistoryPayloadHelper.getMapList(firstNonNull(item.get("toolCalls"), item.get("tool_calls"))));
        boolean hasContent = content != null && !content.isBlank();
        boolean hasReasoning = reasoningContent != null && !reasoningContent.isBlank();
        boolean hasToolCalls = toolCalls != null && !toolCalls.isEmpty();
        if (!hasContent && !hasReasoning && !hasToolCalls) {
            return null;
        }
        AiMessage aiMessage = new AiMessage(hasContent ? content : null);
        if (hasReasoning) {
            aiMessage.setReasoningContent(reasoningContent);
            aiMessage.setFullReasoningContent(reasoningContent);
        }
        if (hasToolCalls) {
            aiMessage.setToolCalls(toolCalls);
        }
        return aiMessage;
    }

    private static ToolMessage toToolMessage(Map<String, Object> item) {
        if (item == null || item.isEmpty()) {
            return null;
        }
        String content = stringValue(item.get("content"));
        String toolCallId = stringValue(firstNonNull(item.get("toolCallId"), item.get("tool_call_id")));
        if ((content == null || content.isBlank()) && (toolCallId == null || toolCallId.isBlank())) {
            return null;
        }
        ToolMessage toolMessage = new ToolMessage();
        toolMessage.setContent(content);
        toolMessage.setToolCallId(toolCallId);
        return toolMessage;
    }

    private static List<ToolCall> toToolCalls(List<Map<String, Object>> rawToolCalls) {
        if (rawToolCalls == null || rawToolCalls.isEmpty()) {
            return null;
        }
        List<ToolCall> toolCalls = new ArrayList<>(rawToolCalls.size());
        for (Map<String, Object> rawToolCall : rawToolCalls) {
            ToolCall toolCall = new ToolCall();
            toolCall.setId(stringValue(rawToolCall.get("id")));
            toolCall.setName(stringValue(firstNonNull(rawToolCall.get("name"), rawToolCall.get("toolName"))));
            toolCall.setArguments(stringValue(rawToolCall.get("arguments")));
            toolCalls.add(toolCall);
        }
        return toolCalls;
    }

    private static Object firstNonNull(Object first, Object second) {
        return first != null ? first : second;
    }

    private static String stringValue(Object value) {
        return value == null ? null : String.valueOf(value);
    }
}
