package inspire

import (
	"encoding/json"
	"net/http"
	"strings"

	"apps/backend/internal/middleware"
	"apps/backend/internal/response"
	"apps/backend/internal/svc"
	"apps/backend/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
	"github.com/zeromicro/go-zero/rest/httpx"
)

// ChatStreamHandler — SSE 串流靈感聊天／產文。
// 事件（每行 data: JSON）：
//
//	{"type":"delta","text":"..."}
//	{"type":"done","session":{...},"message_id":"..."}
//	{"type":"error","message":"..."}
func ChatStreamHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var req types.InspireChatReq
		if err := httpx.Parse(r, &req); err != nil {
			httpx.ErrorCtx(r.Context(), w, err)
			return
		}
		uid, ok := middleware.UIDFrom(r.Context())
		if !ok || uid <= 0 {
			httpx.ErrorCtx(r.Context(), w, response.Biz(401, 401001, "missing authorization"))
			return
		}
		if svcCtx.Inspire == nil {
			httpx.ErrorCtx(r.Context(), w, response.Biz(503, 503001, "inspire not configured"))
			return
		}

		flusher, ok := w.(http.Flusher)
		if !ok {
			httpx.ErrorCtx(r.Context(), w, response.Biz(500, 500000, "streaming unsupported"))
			return
		}

		w.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
		w.Header().Set("Cache-Control", "no-cache, no-transform")
		w.Header().Set("Connection", "keep-alive")
		w.Header().Set("X-Accel-Buffering", "no")
		w.WriteHeader(http.StatusOK)
		flusher.Flush()

		writeEvent := func(v any) bool {
			b, err := json.Marshal(v)
			if err != nil {
				return false
			}
			if _, err := w.Write([]byte("data: ")); err != nil {
				return false
			}
			if _, err := w.Write(b); err != nil {
				return false
			}
			if _, err := w.Write([]byte("\n\n")); err != nil {
				return false
			}
			flusher.Flush()
			return true
		}

		mode := strings.TrimSpace(req.Mode)
		if mode == "" {
			mode = "chat"
		}
		out, err := svcCtx.Inspire.ChatStream(r.Context(), uid, req.Message, req.PinnedIds, mode, req.PersonaId, req.SessionId, req.Material, req.UseWeb, func(chunk string) error {
			if chunk == "" {
				return nil
			}
			if !writeEvent(map[string]any{"type": "delta", "text": chunk}) {
				return http.ErrAbortHandler // client gone
			}
			return nil
		})
		if err != nil {
			_ = writeEvent(map[string]any{"type": "error", "message": err.Error()})
			return
		}
		sess := out.Session
		pub := types.SessionFromDomain(sess)
		msgID := ""
		if len(sess.Messages) > 0 {
			msgID = sess.Messages[len(sess.Messages)-1].ID
		}
		// 回傳實際送 AI 的 prompt 指紋／全文，供前端與預覽對照
		_ = writeEvent(map[string]any{
			"type":               "done",
			"session":            pub,
			"message_id":         msgID,
			"prompt":             out.Prompt,
			"prompt_fingerprint": out.Fingerprint,
			"prompt_char_count":  out.CharCount,
			"prompt_rune_count":  out.RuneCount,
			"prompt_sections":    out.Sections,
		})
		logx.WithContext(r.Context()).Infof("inspire chat-stream ok uid=%d mode=%s fp=%s chars=%d", uid, mode, out.Fingerprint, out.CharCount)
	}
}
