package com.yaoai.api.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.yaoai.agent.service.AgentRunService;
import com.yaoai.agent.sse.AgentSseManager;
import com.yaoai.api.dto.agent.AgentRunDTO;
import com.yaoai.api.dto.agent.AgentStartRequest;
import com.yaoai.common.exception.BizException;
import com.yaoai.common.exception.ErrorCode;
import com.yaoai.common.response.ApiResponse;
import com.yaoai.domain.entity.GraphRun;
import com.yaoai.domain.entity.GraphStep;
import com.yaoai.security.context.TenantContext;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Slf4j
@Tag(name = "Agent 制作中心")
@RestController
@RequestMapping("/agent")
@RequiredArgsConstructor
public class AgentController {

    private final AgentRunService agentRunService;
    private final AgentSseManager sseManager;

    @Operation(summary = "启动 Agent 制作流程")
    @PostMapping("/projects/{projectId}/runs")
    public ApiResponse<AgentRunDTO> startRun(@PathVariable Long projectId,
                                             @Valid @RequestBody AgentStartRequest req) {
        Long tenantId = TenantContext.get();
        GraphRun run = agentRunService.startRun(projectId, tenantId, req.getGoal());
        List<GraphStep> steps = agentRunService.getSteps(run.getId(), tenantId);
        return ApiResponse.success(AgentRunDTO.from(run, steps));
    }

    @Operation(summary = "查询 Run 状态及所有步骤")
    @GetMapping("/runs/{runId}")
    public ApiResponse<AgentRunDTO> getRun(@PathVariable Long runId) {
        Long tenantId = TenantContext.get();
        GraphRun run = agentRunService.getRun(runId, tenantId);
        List<GraphStep> steps = agentRunService.getSteps(runId, tenantId);
        return ApiResponse.success(AgentRunDTO.from(run, steps));
    }

    @Operation(summary = "获取项目最新 Run")
    @GetMapping("/projects/{projectId}/runs/latest")
    public ApiResponse<AgentRunDTO> getLatestRun(@PathVariable Long projectId) {
        Long tenantId = TenantContext.get();
        GraphRun run = agentRunService.getLatestRun(projectId, tenantId);
        if (run == null) return ApiResponse.success(null);
        List<GraphStep> steps = agentRunService.getSteps(run.getId(), tenantId);
        return ApiResponse.success(AgentRunDTO.from(run, steps));
    }

    @Operation(summary = "SSE 实时进度流（token 通过 ?Authorization=xxx 传入）")
    @GetMapping(value = "/runs/{runId}/events", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter subscribe(@PathVariable Long runId,
                                @RequestParam(required = false) String Authorization,
                                HttpServletResponse response) throws IOException {
        // SSE 不能发 custom header，token 通过 query param 传入，此处手动校验
        if (Authorization == null || Authorization.isBlank()) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Missing token");
            return null;
        }
        try {
            Object loginId = StpUtil.getLoginIdByToken(Authorization);
            if (loginId == null) throw new RuntimeException("invalid token");
            Object tenantId = StpUtil.getSessionByLoginId(loginId).get("tenantId");
            if (tenantId != null) {
                TenantContext.set(((Number) tenantId).longValue());
            }
        } catch (Exception e) {
            log.warn("SSE auth failed: runId={}, reason={}", runId, e.getMessage());
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token");
            return null;
        }
        return sseManager.subscribe(runId);
    }

    @Operation(summary = "暂停 Run")
    @PostMapping("/runs/{runId}/pause")
    public ApiResponse<Void> pauseRun(@PathVariable Long runId) {
        Long tenantId = TenantContext.get();
        agentRunService.pauseRun(runId, tenantId);
        return ApiResponse.success(null);
    }

    @Operation(summary = "继续 Run")
    @PostMapping("/runs/{runId}/resume")
    public ApiResponse<Void> resumeRun(@PathVariable Long runId) {
        Long tenantId = TenantContext.get();
        agentRunService.resumeRun(runId, tenantId);
        return ApiResponse.success(null);
    }
}
