package viral

import (
	"encoding/json"
	"fmt"
	"strings"
)

// MissionResearchMap is the structured copy-mission research map (single LLM call).
type MissionResearchMap struct {
	AudienceSummary string         `json:"audienceSummary"`
	ContentGoal     string         `json:"contentGoal"`
	Questions       []string       `json:"questions"`
	Pillars         []string       `json:"pillars"`
	Exclusions      []string       `json:"exclusions"`
	SuggestedTags   []SuggestedTag `json:"suggestedTags"`
	BenchmarkNotes  string         `json:"benchmarkNotes"`
}

func BuildMissionResearchMapSystemPrompt() string {
	return strings.TrimSpace(`你是 Threads 爆款／對標研究顧問。目標：幫創作者找到「近期熱門、高互動、值得仿寫」的話題與搜尋方向。

規則：
1. audienceSummary：必填，2～4 句描述「受眾是誰」（年齡／情境／痛點／會在 Threads 搜什麼），不要只寫人設本人
2. 聚焦「最近會在 Threads 被搜、被討論」的話題，不要寫成學術報告
3. contentGoal：找到近期互動佳、結構可模仿的爆款貼文
4. pillars：可模仿方向（語錄型、故事型、清單型等），至少 4 個；**必須是字串陣列**，不要用 {title:...} 物件
5. questions：受眾會搜的短問題，5+ 個；字串陣列
6. exclusions：不要模仿的內容，至少 4 個；字串陣列
7. suggestedTags：6～8 個「像真人會在 Threads 搜尋框打的字」
   - 每個含 tag, reason, searchIntent（痛點|知識|經驗|對比|工具|語錄）, searchType（短詞|情境|語錄）
   - tag 2～10 字，不要標點、不要完整句子、不要像文章標題
8. benchmarkNotes：怎樣算值得仿的爆款（互動、hook 清楚）
9. 繁體中文；只回傳 JSON（含 audienceSummary）`)
}

func BuildMissionResearchMapUserPrompt(in CopyResearchMapInput) string {
	var b strings.Builder
	b.WriteString("【任務名稱】")
	b.WriteString(strings.TrimSpace(in.Label))
	b.WriteString("\n【種子關鍵字／近期熱詞】")
	b.WriteString(strings.TrimSpace(in.SeedQuery))
	b.WriteString("\n【這次想找什麼】\n")
	b.WriteString(strings.TrimSpace(in.Brief))
	if p := strings.TrimSpace(in.Persona); p != "" {
		b.WriteString("\n【我的人設（仿寫時會套用，地圖請對準受眾與話題，不要只寫我自己）】\n")
		b.WriteString(p)
	}
	if bench := strings.TrimSpace(in.StyleBenchmark); bench != "" {
		b.WriteString("\n【長期對標帳號參考】@")
		b.WriteString(strings.TrimPrefix(bench, "@"))
		b.WriteString("\n")
	}
	if aud := strings.TrimSpace(in.PersonaAudienceSummary); aud != "" {
		b.WriteString("\n【人設層級受眾研究（請延伸為本次任務受眾，勿只複製）】\n")
		b.WriteString(aud)
		if goal := strings.TrimSpace(in.PersonaContentGoal); goal != "" {
			b.WriteString("\n內容目標參考：")
			b.WriteString(goal)
		}
		if len(in.PersonaQuestions) > 0 {
			b.WriteString("\n受眾提問參考：")
			b.WriteString(strings.Join(in.PersonaQuestions, "、"))
		}
		if len(in.PersonaPillars) > 0 {
			b.WriteString("\n內容支柱參考：")
			b.WriteString(strings.Join(in.PersonaPillars, "、"))
		}
		b.WriteString("\n")
	}
	b.WriteString("\n請產出拷貝任務研究地圖 JSON（必填 audienceSummary 與 suggestedTags 陣列）。")
	return b.String()
}

func ParseMissionResearchMapOutput(raw string) (MissionResearchMap, error) {
	payload, err := extractCopyMapJSON(raw)
	if err != nil {
		return MissionResearchMap{}, err
	}
	var root map[string]json.RawMessage
	if err := json.Unmarshal(payload, &root); err != nil {
		return MissionResearchMap{}, fmt.Errorf("parse mission research map: %w", err)
	}
	out := MissionResearchMap{
		AudienceSummary: firstJSONString(root, "audienceSummary", "audience_summary"),
		ContentGoal:     firstJSONString(root, "contentGoal", "content_goal"),
		BenchmarkNotes:  firstJSONString(root, "benchmarkNotes", "benchmark_notes"),
		Questions:       parseFlexibleStringList(pickRawMessage(root, "questions")),
		Pillars:         parseFlexibleStringList(pickRawMessage(root, "pillars")),
		Exclusions:      parseFlexibleStringList(pickRawMessage(root, "exclusions")),
		SuggestedTags:   parseFlexibleSuggestedTags(pickRawMessage(root, "suggestedTags", "suggested_tags")),
	}
	if strings.TrimSpace(out.AudienceSummary) == "" {
		return MissionResearchMap{}, fmt.Errorf("mission research map missing audienceSummary")
	}
	if len(out.SuggestedTags) < 4 {
		return MissionResearchMap{}, fmt.Errorf("mission research map needs at least 4 suggested tags")
	}
	return out, nil
}

func cleanSuggestedTags(tags []SuggestedTag) []SuggestedTag {
	out := []SuggestedTag{}
	seen := map[string]struct{}{}
	for _, item := range tags {
		tag := strings.TrimSpace(item.Tag)
		if tag == "" {
			continue
		}
		if _, ok := seen[tag]; ok {
			continue
		}
		seen[tag] = struct{}{}
		out = append(out, SuggestedTag{
			Tag:          tag,
			Reason:       strings.TrimSpace(item.Reason),
			SearchIntent: strings.TrimSpace(item.SearchIntent),
			SearchType:   strings.TrimSpace(item.SearchType),
		})
	}
	return out
}

func ToEntityMissionResearchMap(m MissionResearchMap) map[string]any {
	tags := make([]map[string]any, 0, len(m.SuggestedTags))
	for _, item := range m.SuggestedTags {
		tags = append(tags, map[string]any{
			"tag":           item.Tag,
			"reason":        item.Reason,
			"search_intent": item.SearchIntent,
			"search_type":   item.SearchType,
		})
	}
	return map[string]any{
		"audience_summary": m.AudienceSummary,
		"content_goal":     m.ContentGoal,
		"questions":        m.Questions,
		"pillars":          m.Pillars,
		"exclusions":       m.Exclusions,
		"suggested_tags":   tags,
		"benchmark_notes":  m.BenchmarkNotes,
	}
}
