package cn.nianxx.thhotel.integrations.ai.superagent.service.impl;

import cn.nianxx.thhotel.integrations.ai.superagent.common.result.SuperAgentOpenApiResult;
import cn.nianxx.thhotel.integrations.ai.superagent.common.result.SuperAgentOpenApiTraceEvent;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import org.springframework.stereotype.Component;

/**
 * SuperAgent SSE 响应解析器。优先从 values/messages 中提取 finish_reason=stop 的最终 AI 回答。
 */
@Component
public class SuperAgentOpenApiSseParser {

    private static final Pattern JSON_SECRET_PATTERN = Pattern.compile(
            "(?i)(\"(?:api[_-]?key|token|secret|password|cookie|authorization)\"\\s*:\\s*\")[^\"]*(\")");
    private static final Pattern HEADER_SECRET_PATTERN = Pattern.compile(
            "(?i)((?:authorization|cookie)\\s*:\\s*)[^\\s,;]+");
    private static final Pattern TEXT_SECRET_PATTERN = Pattern.compile(
            "(?i)((?:api[_-]?key|token|secret|password)\\s*[=:]\\s*)[^\\s,;}]+");

    private final ObjectMapper objectMapper;

    /**
     * 使用默认 ObjectMapper，便于单元测试直接 new。
     */
    public SuperAgentOpenApiSseParser() {
        this(new ObjectMapper());
    }

    /**
     * 注入 JSON 解析器。
     */
    public SuperAgentOpenApiSseParser(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    /**
     * 解析 SSE 文本，返回最终 AI 回答和调用元数据。
     */
    public SuperAgentOpenApiResult parse(String sessionId, String sseBody) {
        return parse(sessionId, sseBody, traceEvent -> {
        });
    }

    /**
     * 解析 SSE 文本，边解析边回调 SuperAgent 公开 Trace 事件。
     */
    public SuperAgentOpenApiResult parse(
            String sessionId,
            String sseBody,
            Consumer<SuperAgentOpenApiTraceEvent> traceConsumer) {
        if (sseBody == null || sseBody.isBlank()) {
            throw new SuperAgentOpenApiException("SuperAgent SSE 响应为空。");
        }
        return parse(sessionId, new StringReader(sseBody), traceConsumer);
    }

    /**
     * 从 Reader 流式解析 SSE，适用于 Open API 长连接响应。
     */
    public SuperAgentOpenApiResult parse(
            String sessionId,
            Reader reader,
            Consumer<SuperAgentOpenApiTraceEvent> traceConsumer) {
        if (reader == null) {
            throw new SuperAgentOpenApiException("SuperAgent SSE 响应为空。");
        }
        Set<String> eventTypes = new LinkedHashSet<>();
        ParsedState state = new ParsedState();
        try {
            parseLines(reader, event -> {
                eventTypes.add(event.eventType());
                consumeEvent(event, state, safeTraceConsumer(traceConsumer));
            }, state);
        } catch (IOException exception) {
            throw new SuperAgentOpenApiException("SuperAgent SSE 读取失败。", exception);
        }
        return buildResult(sessionId, eventTypes, state);
    }

    /**
     * 汇总解析状态并生成结果对象。
     */
    private SuperAgentOpenApiResult buildResult(String sessionId, Set<String> eventTypes, ParsedState state) {
        if (!state.endSeen) {
            throw new SuperAgentOpenApiException("SuperAgent SSE 未收到结束事件。");
        }
        if ((state.rawAnswer == null || state.rawAnswer.isBlank()) && state.fallbackRawAnswer != null) {
            state.rawAnswer = state.fallbackRawAnswer;
            state.modelName = state.fallbackModelName;
            state.inputTokens = state.fallbackInputTokens;
            state.outputTokens = state.fallbackOutputTokens;
            state.totalTokens = state.fallbackTotalTokens;
        }
        if (state.rawAnswer == null || state.rawAnswer.isBlank()) {
            throw new SuperAgentOpenApiException("SuperAgent SSE 未找到最终 AI 回答。");
        }
        return new SuperAgentOpenApiResult(
                sessionId,
                state.runId,
                state.profileId,
                state.profileVersionId,
                state.modelName,
                state.rawAnswer,
                state.inputTokens,
                state.outputTokens,
                state.totalTokens,
                List.copyOf(eventTypes),
                List.copyOf(state.traceEvents));
    }

    /**
     * 消费单个 SSE 事件。
     */
    private void consumeEvent(
            SseEvent event,
            ParsedState state,
            Consumer<SuperAgentOpenApiTraceEvent> traceConsumer) {
        try {
            if ("end".equals(event.eventType())) {
                state.endSeen = true;
                return;
            }
            JsonNode data = objectMapper.readTree(event.data());
            if ("metadata".equals(event.eventType())) {
                state.runId = text(data, "run_id", state.runId);
                state.profileId = text(data, "resolved_profile_id", state.profileId);
                state.profileVersionId = text(data, "resolved_profile_version_id", state.profileVersionId);
            }
            if ("messages".equals(event.eventType())) {
                consumeMessages(data, state);
            }
            if ("values".equals(event.eventType())) {
                consumeValuesEvent(data, state);
            }
            if ("trace".equals(event.eventType())) {
                consumeTraceEvent(data, state, traceConsumer);
            }
        } catch (Exception exception) {
            throw new SuperAgentOpenApiException("SuperAgent SSE JSON 解析失败。", exception);
        }
    }

    /**
     * 从 values.messages 中提取最终 AI 消息和 token 用量。
     */
    private void consumeValuesEvent(JsonNode data, ParsedState state) {
        JsonNode messages = data.path("messages");
        consumeMessages(messages, state);
    }

    /**
     * 兼容单条 message、messages 数组以及包装在 messages 字段中的聚合结构。
     */
    private void consumeMessages(JsonNode data, ParsedState state) {
        if (data == null || data.isMissingNode() || data.isNull()) {
            return;
        }
        if (data.isArray()) {
            for (JsonNode message : data) {
                consumeAiMessage(message, state);
            }
            return;
        }
        JsonNode messages = data.path("messages");
        if (messages.isArray()) {
            consumeMessages(messages, state);
            return;
        }
        consumeAiMessage(data, state);
    }

    /**
     * 提取 AI 消息内容。finish_reason=stop 的内容优先，非 stop 内容只作为流正常结束后的兜底。
     */
    private void consumeAiMessage(JsonNode message, ParsedState state) {
        if (!"ai".equals(message.path("type").asText())) {
            return;
        }
        String content = contentText(message.path("content"));
        if (content == null || content.isBlank()) {
            return;
        }
        JsonNode responseMetadata = message.path("response_metadata");
        JsonNode usage = message.path("usage_metadata");
        String modelName = text(responseMetadata, "model_name", state.modelName);
        String finishReason = responseMetadata.path("finish_reason").asText();
        if ("stop".equals(finishReason)) {
            state.rawAnswer = content;
            state.modelName = modelName;
            state.inputTokens = intValue(usage, "input_tokens", state.inputTokens);
            state.outputTokens = intValue(usage, "output_tokens", state.outputTokens);
            state.totalTokens = intValue(usage, "total_tokens", state.totalTokens);
            return;
        }
        state.fallbackRawAnswer = content;
        state.fallbackModelName = modelName;
        state.fallbackInputTokens = intValue(usage, "input_tokens", state.fallbackInputTokens);
        state.fallbackOutputTokens = intValue(usage, "output_tokens", state.fallbackOutputTokens);
        state.fallbackTotalTokens = intValue(usage, "total_tokens", state.fallbackTotalTokens);
    }

    /**
     * 消费公开 Trace 事件，只提取可展示摘要字段。
     */
    private void consumeTraceEvent(
            JsonNode data,
            ParsedState state,
            Consumer<SuperAgentOpenApiTraceEvent> traceConsumer) {
        JsonNode trace = data.path("data").isObject() && data.path("event").isMissingNode()
                ? data.path("data")
                : data;
        JsonNode toolCalls = trace.path("tool_calls");
        if (toolCalls.isArray() && !toolCalls.isEmpty()) {
            for (JsonNode toolCall : toolCalls) {
                emitTraceEvent(traceEvent(trace, toolCall), state, traceConsumer);
            }
            return;
        }
        emitTraceEvent(traceEvent(trace, trace), state, traceConsumer);
    }

    /**
     * 构造公开 Trace 事件对象。
     */
    private SuperAgentOpenApiTraceEvent traceEvent(JsonNode trace, JsonNode detail) {
        return new SuperAgentOpenApiTraceEvent(
                safeTraceText(text(trace, "event", null)),
                safeTraceText(text(trace, "run_id", null)),
                safeTraceText(text(trace, "message_id", null)),
                safeTraceText(text(detail, "tool_call_id", text(trace, "tool_call_id", null))),
                safeTraceText(text(detail, "name", text(trace, "name", null))),
                safeTraceText(text(trace, "text", null)),
                safeTraceText(summary(detail.path("input"), summary(trace.path("input"), null))),
                safeTraceText(summary(detail.path("output"), summary(trace.path("output"), null))),
                safeTraceText(text(trace, "status", null)),
                safeTraceText(text(trace, "ts", null)));
    }

    /**
     * 保存并回调 Trace 事件。
     */
    private void emitTraceEvent(
            SuperAgentOpenApiTraceEvent traceEvent,
            ParsedState state,
            Consumer<SuperAgentOpenApiTraceEvent> traceConsumer) {
        if (traceEvent.event() == null || traceEvent.event().isBlank()) {
            return;
        }
        state.traceEvents.add(traceEvent);
        traceConsumer.accept(traceEvent);
    }

    /**
     * 流式拆分 SSE 事件块，支持多行 data。
     */
    private void parseLines(Reader reader, Consumer<SseEvent> consumer, ParsedState state) throws IOException {
        BufferedReader bufferedReader = reader instanceof BufferedReader existingReader
                ? existingReader
                : new BufferedReader(reader);
        SseEventBuilder builder = new SseEventBuilder();
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            if (line.isBlank()) {
                flushEvent(builder, consumer);
                if (state.endSeen) {
                    return;
                }
                continue;
            }
            if (line.startsWith(":")) {
                continue;
            }
            if (line.startsWith("event:")) {
                builder.eventType(line.substring("event:".length()).trim());
                continue;
            }
            if (line.startsWith("data:")) {
                builder.appendData(line.substring("data:".length()).trim());
            }
        }
        flushEvent(builder, consumer);
    }

    /**
     * 输出当前累积事件并重置 builder。
     */
    private void flushEvent(SseEventBuilder builder, Consumer<SseEvent> consumer) {
        SseEvent event = builder.build();
        if (event != null) {
            consumer.accept(event);
        }
        builder.reset();
    }

    /**
     * 读取文本字段，缺失时保留已有值。
     */
    private String text(JsonNode node, String fieldName, String fallback) {
        JsonNode value = node.path(fieldName);
        return value.isMissingNode() || value.isNull() ? fallback : value.asText();
    }

    /**
     * 读取整数字段，缺失时保留已有值。
     */
    private Integer intValue(JsonNode node, String fieldName, Integer fallback) {
        JsonNode value = node.path(fieldName);
        if (value.isMissingNode() || value.isNull()) {
            return fallback;
        }
        return value.asInt();
    }

    /**
     * 读取公开 summary 字段。
     */
    private String summary(JsonNode node, String fallback) {
        if (node == null || node.isMissingNode() || node.isNull()) {
            return fallback;
        }
        String value = text(node, "summary", null);
        if (value != null) {
            return value;
        }
        return node.isTextual() ? node.asText() : fallback;
    }

    /**
     * Trace 展示字段做短文本脱敏与截断。
     */
    private String safeTraceText(String value) {
        if (value == null || value.isBlank()) {
            return null;
        }
        String sanitized = JSON_SECRET_PATTERN.matcher(value).replaceAll("$1***$2");
        sanitized = HEADER_SECRET_PATTERN.matcher(sanitized).replaceAll("$1***");
        sanitized = TEXT_SECRET_PATTERN.matcher(sanitized).replaceAll("$1***");
        return sanitized.length() > 2048 ? sanitized.substring(0, 2048) : sanitized;
    }

    /**
     * Trace 消费者为空时使用 no-op。
     */
    private Consumer<SuperAgentOpenApiTraceEvent> safeTraceConsumer(
            Consumer<SuperAgentOpenApiTraceEvent> traceConsumer) {
        return traceConsumer == null ? traceEvent -> {
        } : traceConsumer;
    }

    /**
     * 读取 AI content，兼容字符串、文本片段数组和简单文本对象。
     */
    private String contentText(JsonNode content) {
        if (content == null || content.isMissingNode() || content.isNull()) {
            return null;
        }
        if (content.isTextual()) {
            return content.asText();
        }
        if (content.isArray()) {
            StringBuilder builder = new StringBuilder();
            for (JsonNode item : content) {
                appendContentText(builder, contentText(item));
            }
            return builder.isEmpty() ? null : builder.toString();
        }
        if (content.isObject()) {
            String text = contentText(content.path("text"));
            if (text != null && !text.isBlank()) {
                return text;
            }
            text = contentText(content.path("content"));
            return text == null || text.isBlank() ? content.toString() : text;
        }
        return null;
    }

    /**
     * 拼接数组型 content 中的非空文本片段。
     */
    private void appendContentText(StringBuilder builder, String text) {
        if (text == null || text.isBlank()) {
            return;
        }
        if (!builder.isEmpty()) {
            builder.append('\n');
        }
        builder.append(text);
    }

    /**
     * SSE 单事件。
     */
    private record SseEvent(String eventType, String data) {
    }

    /**
     * SSE 事件累积器。
     */
    private static final class SseEventBuilder {
        private String eventType = "message";
        private final StringBuilder data = new StringBuilder();

        private void eventType(String eventType) {
            this.eventType = eventType == null || eventType.isBlank() ? "message" : eventType;
        }

        private void appendData(String value) {
            if (!data.isEmpty()) {
                data.append('\n');
            }
            data.append(value);
        }

        private SseEvent build() {
            if (data.isEmpty() && !"end".equals(eventType)) {
                return null;
            }
            return new SseEvent(eventType, data.toString());
        }

        private void reset() {
            eventType = "message";
            data.setLength(0);
        }
    }

    /**
     * SSE 解析过程中的可变状态。
     */
    private static final class ParsedState {
        private boolean endSeen;
        private String runId;
        private String profileId;
        private String profileVersionId;
        private String modelName;
        private String rawAnswer;
        private Integer inputTokens;
        private Integer outputTokens;
        private Integer totalTokens;
        private String fallbackRawAnswer;
        private String fallbackModelName;
        private Integer fallbackInputTokens;
        private Integer fallbackOutputTokens;
        private Integer fallbackTotalTokens;
        private final List<SuperAgentOpenApiTraceEvent> traceEvents = new ArrayList<>();
    }
}
