package com.infoepoch.pms.agent.controller;

import com.infoepoch.pms.agent.common.LogHelper;
import com.infoepoch.pms.agent.domain.care.CareAgentService;
import com.infoepoch.pms.agent.domain.care.log.CareTraceLogSupport;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/agent")
public class AgentChatController {
    private final CareAgentService careAgentService;

    /**
     * 推荐场景的标准 GET 方式的流式聊天入口。
     */
    @GetMapping(value = "/care/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> streamCareAgent(@RequestParam("sessionId") String sessionId,
                                                         @RequestParam("message") String message) {
        return streamCareAgentInternal(sessionId, message);
    }

    /**
     * 将领域服务输出统一封装成 SSE 事件流。
     */
    private Flux<ServerSentEvent<String>> streamCareAgentInternal(String sessionId, String message) {
        String traceId = CareTraceLogSupport.newTraceId();
        LogHelper.info(this, CareTraceLogSupport.format(
                traceId,
                sessionId,
                "流式请求开始",
                "收到请求，" + CareTraceLogSupport.safeMessageSummary(message)
        ));
        if (!StringUtils.hasText(sessionId)) {
            LogHelper.info(this, CareTraceLogSupport.format(
                    traceId,
                    sessionId,
                    "参数校验失败",
                    "sessionId为空"
            ));
            return Flux.just(buildEvent("error", "sessionId不能为空"));
        }
        return careAgentService.streamChat(traceId, sessionId, message)
                .map(chunk -> buildEvent("message", chunk))
                .concatWithValues(buildEvent("done", "[DONE]"))
                .doOnComplete(() -> LogHelper.info(this, CareTraceLogSupport.format(
                        traceId,
                        sessionId,
                        "流式请求完成",
                        "SSE输出完成"
                )))
                .doOnError(error -> LogHelper.error(this, CareTraceLogSupport.format(
                        traceId,
                        sessionId,
                        "流式请求异常",
                        "SSE输出失败，异常=" + CareTraceLogSupport.safeText(resolveErrorMessage(error))
                ), error))
                .onErrorResume(error -> Flux.just(buildEvent("error", resolveErrorMessage(error))));
    }

    /**
     * 构造统一的 SSE 消息事件。
     */
    private ServerSentEvent<String> buildEvent(String event, String data) {
        return ServerSentEvent.<String>builder()
                .event(event)
                .data(data)
                .build();
    }

    /**
     * 将异常转换成可直接返回给前端的错误文案。
     */
    private String resolveErrorMessage(Throwable error) {
        return StringUtils.hasText(error.getMessage()) ? error.getMessage() : "careAgent流式调用失败";
    }
}

