package com.agent.management.controller;

import com.agent.management.common.Result;
import com.agent.management.engine.HermesRunResult;
import com.agent.management.engine.hermes.HermesBridgeClient;
import com.agent.management.external.SseEventBus;
import com.agent.management.model.dto.SkillDTO;
import com.agent.management.model.dto.SkillGenerationRequest;
import com.agent.management.model.dto.SkillRefineRequest;
import com.agent.management.model.dto.SkillRefineResponse;
import com.agent.management.model.vo.SkillVO;
import com.agent.management.service.SkillGenerationService;
import com.agent.management.service.SkillService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 技能生成入口：选择具备生成能力的技能，输入需求，
 * 由后端调用 Hermes Bridge 在临时工作目录中生成新技能并落盘到全局 skills 目录。
 */
@Slf4j
@RestController
@RequestMapping("/api/skills")
@RequiredArgsConstructor
public class SkillGenerationController {

    private final SkillGenerationService generationService;
    private final SkillService skillService;
    private final SseEventBus eventBus;
    private final ObjectProvider<HermesBridgeClient> bridgeClientProvider;
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 用于"智能润色"快速调用的技能 folderName（在该技能缺省时回退）
     */
    private static final String DEFAULT_REFINE_SKILL = "military-workflow-spec";
    /**
     * "快速返回、不深度思考"的最大工具调用轮次
     */
    private static final int REFINE_MAX_ITERATIONS = 30;

    /**
     * 列出所有具备生成其他技能能力的技能（canGenerateSkill=true）
     */
    @GetMapping("/generators")
    public Result<List<SkillVO>> listGenerators() {
        List<SkillVO> list = skillService.listSkills().stream()
                .filter(SkillDTO::isCanGenerateSkill)
                .map(dto -> {
                    SkillVO vo = new SkillVO();
                    vo.setFolderName(dto.getFolderName());
                    vo.setName(dto.getName());
                    vo.setDisplayName(dto.getDisplayName());
                    vo.setDescription(dto.getDescription());
                    vo.setCanGenerateSkill(true);
                    vo.setInputs(dto.getInputs());
                    vo.setOutputs(dto.getOutputs());
                    return vo;
                })
                .collect(Collectors.toList());
        return Result.success(list);
    }

    /**
     * 启动一次技能生成任务（异步执行）。
     * 返回 runId，客户端用此 ID 订阅 SSE 流或轮询状态。
     */
    @PostMapping("/generate")
    public Result<Map<String, String>> startGeneration(@RequestBody SkillGenerationRequest request) {
        String runId = generationService.startGeneration(request);
        Map<String, String> result = new HashMap<>();
        result.put("runId", runId);
        result.put("streamUrl", "/api/skills/generate/" + runId + "/stream");
        result.put("statusUrl", "/api/skills/generate/" + runId + "/status");
        return Result.success("已启动生成", result);
    }

    /**
     * 订阅生成任务的 SSE 流：实时推送 thinking / tool_call / tool_result / status，
     * 终止事件为 workflow_complete（含 generatedFolderName）或 workflow_error。
     *
     * EventSource 不支持自定义 header，因此 Last-Event-ID 既支持 header 也支持 query 参数。
     */
    @GetMapping(value = "/generate/{runId}/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public ResponseEntity<SseEmitter> streamGeneration(
            @PathVariable String runId,
            @RequestHeader(value = "Last-Event-ID", required = false) Long lastEventIdHeader,
            @RequestParam(value = "lastEventId", required = false) Long lastEventIdQuery) {
        Long lastEventId = lastEventIdHeader != null ? lastEventIdHeader : lastEventIdQuery;
        if (!eventBus.exists(runId)) {
            return ResponseEntity.notFound().build();
        }
        SseEmitter emitter = eventBus.subscribe(runId, lastEventId);
        if (emitter == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok()
                .header("X-Accel-Buffering", "no")
                .header("Cache-Control", "no-cache")
                .body(emitter);
    }

    /**
     * 查询生成状态（轻量轮询兜底，建议优先使用 SSE 流）。
     */
    @GetMapping("/generate/{runId}/status")
    public Result<Map<String, Object>> getStatus(@PathVariable String runId) {
        var state = generationService.getState(runId);
        if (state == null) {
            return Result.error(404, "runId 不存在或已过期");
        }
        Map<String, Object> result = new HashMap<>();
        result.put("runId", state.getRunId());
        result.put("status", state.getStatus() != null ? state.getStatus().name() : "UNKNOWN");
        result.put("generatorSkillFolder", state.getGeneratorSkillFolder());
        result.put("name", state.getName());
        result.put("generatedFolderName", state.getGeneratedFolderName());
        result.put("errorMessage", state.getErrorMessage());
        result.put("createdAt", state.getCreatedAt());
        result.put("completedAt", state.getCompletedAt());
        return Result.success(result);
    }

    /**
     * 智能润色：将用户输入的需求文本交给指定技能（默认 military-workflow-spec）做规格化处理。
     *
     * <p>同步阻塞调用 Hermes Bridge，使用较小的 maxIterations 实现"快速返回、不深度思考"。
     * 期望技能返回 JSON：{@code { status, message, prompt }}。
     * 解析失败时降级为 warning，并将原始文本作为 prompt 返回。
     */
    @PostMapping("/refine")
    public Result<SkillRefineResponse> refineRequirement(@RequestBody SkillRefineRequest request) {
        if (request.getUserInput() == null || request.getUserInput().isBlank()) {
            return Result.error(400, "需求文本不能为空");
        }

        HermesBridgeClient bridgeClient = bridgeClientProvider.getIfAvailable();
        if (bridgeClient == null) {
            return Result.error(503, "Hermes Bridge 未启用，无法执行智能润色");
        }

        String refineSkillFolder = (request.getRefineSkillFolder() == null || request.getRefineSkillFolder().isBlank())
                ? DEFAULT_REFINE_SKILL : request.getRefineSkillFolder();

        String systemPrompt;
        try {
            systemPrompt = skillService.getSkillFullContent(refineSkillFolder);
        } catch (Exception e) {
            log.warn("[Refine] 加载技能 {} 失败: {}", refineSkillFolder, e.getMessage());
            return Result.error(404, "技能不存在: " + refineSkillFolder);
        }

        try {
            HermesRunResult runResult = bridgeClient.run(
                    systemPrompt, request.getUserInput(), REFINE_MAX_ITERATIONS);
            SkillRefineResponse response = parseRefineResult(runResult.getFinalText());
            return Result.success(response);
        } catch (Exception e) {
            log.warn("[Refine] Hermes 执行失败: {}", e.getMessage());
            SkillRefineResponse failed = new SkillRefineResponse(
                    "failed", "Hermes 执行失败: " + e.getMessage(), "");
            return Result.success(failed);
        }
    }

    /**
     * 解析润色技能返回的 JSON。鲁棒处理：
     * <ol>
     *   <li>直接解析</li>
     *   <li>提取 markdown 代码块中的 JSON</li>
     *   <li>提取首个 {@code {...}} 子串</li>
     * </ol>
     * 三级降级仍失败时返回 warning + 原文作为 prompt。
     */
    private SkillRefineResponse parseRefineResult(String finalText) {
        if (finalText == null || finalText.isBlank()) {
            return new SkillRefineResponse("failed", "润色技能未返回内容", "");
        }

        String json = extractJson(finalText);
        if (json == null) {
            // 非合法 JSON：降级为 warning，原文回写
            return new SkillRefineResponse(
                    "warning", "润色结果不是合法 JSON，已保留原文", finalText.trim());
        }

        try {
            JsonNode node = objectMapper.readTree(json);
            String status = textOrDefault(node, "status", "warning");
            String message = textOrDefault(node, "message", "");
            String prompt = textOrDefault(node, "prompt", "");
            return new SkillRefineResponse(status, message, prompt);
        } catch (Exception e) {
            return new SkillRefineResponse(
                    "warning", "润色结果解析失败: " + e.getMessage(), finalText.trim());
        }
    }

    /**
     * 从可能包含 markdown 代码块或额外文字的文本中提取 JSON 对象。
     */
    private String extractJson(String text) {
        String trimmed = text.trim();
        // 1. 直接是 JSON
        if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
            return trimmed;
        }
        // 2. markdown 代码块 ```json ... ``` 或 ``` ... ```
        int fenceStart = trimmed.indexOf("```");
        if (fenceStart >= 0) {
            int contentStart = trimmed.indexOf('\n', fenceStart);
            if (contentStart > 0) {
                int contentEnd = trimmed.indexOf("```", contentStart + 1);
                if (contentEnd > contentStart) {
                    String inner = trimmed.substring(contentStart + 1, contentEnd).trim();
                    if (inner.startsWith("{") && inner.endsWith("}")) {
                        return inner;
                    }
                }
            }
        }
        // 3. 首个 {...} 子串
        int firstBrace = trimmed.indexOf('{');
        int lastBrace = trimmed.lastIndexOf('}');
        if (firstBrace >= 0 && lastBrace > firstBrace) {
            return trimmed.substring(firstBrace, lastBrace + 1);
        }
        return null;
    }

    private String textOrDefault(JsonNode node, String field, String defaultVal) {
        JsonNode child = node.get(field);
        if (child == null || child.isNull()) return defaultVal;
        return child.asText(defaultVal);
    }
}
