package handler

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"net/http"

	"github.com/gin-gonic/gin"

	"github.com/sundynix/sundynix-shared/contract"
)

// GenerateReport: POST /api/v1/reports —— 触发报告生成。
// 组装一个 intent=report 的任务发到 NATS，Dispatcher 走专用编排（规划→分章并行→渲染 docx）。
// 返回 task_id；客户端用 GET /tasks/:id/stream 看实时进度，完成后用 /reports/:id/download 取 Word。
func (h *Handler) GenerateReport(c *gin.Context) {
	var body struct {
		Topic string `json:"topic"`
		KB    string `json:"kb"`
	}
	if err := c.ShouldBindJSON(&body); err != nil || body.Topic == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "topic required"})
		return
	}
	id := newReportID()
	graph, _ := json.Marshal(map[string]any{"topic": body.Topic}) // 占位 DSL，报告编排实际读 Meta
	task := &contract.Task{
		ID:    id,
		Graph: graph,
		Meta: map[string]any{
			contract.MetaIntent:    contract.IntentReport,
			contract.MetaTopic:     body.Topic,
			contract.MetaKB:        body.KB,
			contract.MetaUserID:    userID(c),
			contract.MetaSessionID: sessionID(c),
		},
	}
	if err := h.bus.PublishTask(c.Request.Context(), task); err != nil {
		c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusAccepted, gin.H{"task_id": id})
}

// ExportReport: GET /api/v1/reports/:id/export?format=docx|md —— 按需把报告源渲染为指定格式并下载。
// 生成阶段只存源；此处经 mcp-go report_export 现渲染（"导出时再处理"）。PDF 由前端打印预览生成。
func (h *Handler) ExportReport(c *gin.Context) {
	id := c.Param("id")
	format := c.DefaultQuery("format", "docx")
	res, err := h.bus.CallTool(c.Request.Context(), contract.ToolSubjectGo("report_export"),
		&contract.ToolCall{Tool: "report_export", Args: map[string]any{"task_id": id, "format": format}})
	if err != nil || res == nil || !res.OK {
		msg := "报告尚未生成或已过期"
		if res != nil && res.Error != "" {
			msg = res.Error
		}
		c.JSON(http.StatusNotFound, gin.H{"error": msg})
		return
	}
	switch format {
	case "md", "markdown":
		c.Header("Content-Disposition", `attachment; filename="`+id+`.md"`)
		c.Header("Content-Type", "text/markdown; charset=utf-8")
		c.String(http.StatusOK, res.Content)
	default: // docx：res.Content 为 mcp-go 落盘的 .docx 路径
		c.Header("Content-Disposition", `attachment; filename="`+id+`.docx"`)
		c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
		c.File(res.Content)
	}
}

func newReportID() string {
	var b [8]byte
	_, _ = rand.Read(b[:])
	return "report_" + hex.EncodeToString(b[:])
}
