package viral

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

type MissionInspireInput struct {
	PersonaDisplayName  string
	PersonaBrief        string
	PersonaBlock        string
	StyleBenchmark      string
	PersonaAudience     string
	PersonaContentGoal  string
	PersonaQuestions    []string
	PersonaPillars      []string
	RecentMissionLabels []string
	RecentSeedQueries   []string
	TrendSnippets       []MissionInspireTrendSnippet
	WebSearchProvider   string
	LLMOnly             bool
}

type MissionInspireTrendSnippet struct {
	Query   string
	Title   string
	Snippet string
	URL     string
}

type MissionInspireOutput struct {
	Label         string
	SeedQuery     string
	Brief         string
	TrendReason   string
	TrendKeywords []string
}

func BuildMissionInspireSystemPrompt() string {
	return strings.TrimSpace(`你是 Threads 拷貝忍者的「靈感骰子」顧問。根據近期網路熱搜、Google Trends 類訊號與創作者人設，產出一組**全新**拷貝任務草稿。

規則：
1. 若【近期趨勢訊號】有內容，從中挑一個適合在 Threads 海巡的方向；不要編造不存在的時事
2. 若趨勢訊號為空（未連線網路搜尋），**必須**改依人設、受眾痛點與常見 Threads 討論型態推測「近期可能被搜尋」的話題，並在 trendReason 說明推測理由（不要假裝有外部熱搜來源）
3. label：任務名稱，6～18 字，像企劃案標題，不要標點堆疊
4. seedQuery：種子關鍵字／近期熱詞，2～6 個詞用頓號或空格分隔，適合當 Threads 搜尋起點
5. brief：這次想找什麼，2～4 句，說明要海巡哪類爆款、語氣或格式偏好
6. trendReason：1～2 句，為何選這個趨勢（可引用訊號來源大意，不要貼 URL）
7. trendKeywords：3～6 個相關熱詞（字串陣列）
8. 避開【近期已做過的任務】相同題材
9. 繁體中文；只回傳 JSON：
{"label":"","seedQuery":"","brief":"","trendReason":"","trendKeywords":[]}`)
}

func BuildMissionInspireUserPrompt(in MissionInspireInput) string {
	var b strings.Builder
	if name := strings.TrimSpace(in.PersonaDisplayName); name != "" {
		b.WriteString("【人設名稱】")
		b.WriteString(name)
		b.WriteString("\n")
	}
	if p := strings.TrimSpace(in.PersonaBlock); p != "" {
		b.WriteString("【人設摘要】\n")
		b.WriteString(p)
		b.WriteString("\n")
	}
	if bench := strings.TrimSpace(in.StyleBenchmark); bench != "" {
		b.WriteString("【對標帳號】@")
		b.WriteString(strings.TrimPrefix(bench, "@"))
		b.WriteString("\n")
	}
	if aud := strings.TrimSpace(in.PersonaAudience); aud != "" {
		b.WriteString("【受眾方向】")
		b.WriteString(aud)
		b.WriteString("\n")
	}
	if goal := strings.TrimSpace(in.PersonaContentGoal); goal != "" {
		b.WriteString("【內容目標】")
		b.WriteString(goal)
		b.WriteString("\n")
	}
	if len(in.PersonaPillars) > 0 {
		b.WriteString("【內容支柱】")
		b.WriteString(strings.Join(in.PersonaPillars, "、"))
		b.WriteString("\n")
	}
	if len(in.RecentMissionLabels) > 0 || len(in.RecentSeedQueries) > 0 {
		b.WriteString("【近期已做過的任務（請避開）】\n")
		for _, label := range in.RecentMissionLabels {
			if label = strings.TrimSpace(label); label != "" {
				b.WriteString("- ")
				b.WriteString(label)
				b.WriteString("\n")
			}
		}
		for _, seed := range in.RecentSeedQueries {
			if seed = strings.TrimSpace(seed); seed != "" {
				b.WriteString("- 種子：")
				b.WriteString(seed)
				b.WriteString("\n")
			}
		}
	}
	if in.LLMOnly {
		b.WriteString("【模式】未設定 Web Search API key，請純依人設與受眾推測靈感（勿假裝有 Google 熱搜）\n")
	} else if provider := strings.TrimSpace(in.WebSearchProvider); provider != "" {
		b.WriteString("【趨勢來源】")
		b.WriteString(provider)
		b.WriteString(" 網路搜尋\n")
	}
	b.WriteString("【近期趨勢訊號】\n")
	if len(in.TrendSnippets) == 0 {
		b.WriteString("（無外部趨勢結果，請改用人設推測近期 Threads 可能熱議方向）\n")
	} else {
		for i, item := range in.TrendSnippets {
			b.WriteString(fmt.Sprintf("[%d] 查詢：%s\n", i+1, strings.TrimSpace(item.Query)))
			if title := strings.TrimSpace(item.Title); title != "" {
				b.WriteString("標題：")
				b.WriteString(title)
				b.WriteString("\n")
			}
			if snippet := strings.TrimSpace(item.Snippet); snippet != "" {
				b.WriteString(snippet)
				b.WriteString("\n")
			}
			b.WriteString("\n")
		}
	}
	b.WriteString("請產出拷貝任務靈感 JSON。")
	return b.String()
}

func InspireTrendSearchQueries(personaBrief, styleBenchmark string) []string {
	queries := []string{
		"Google Trends 台灣 今日 熱門搜尋 關鍵字",
		"Threads 台灣 熱門 話題 最近 一週",
		"近期 網路 熱搜 關鍵字 台灣",
	}
	context := strings.TrimSpace(personaBrief + " " + styleBenchmark)
	if context != "" {
		trimmed := context
		if len([]rune(trimmed)) > 24 {
			trimmed = string([]rune(trimmed)[:24])
		}
		queries = append(queries, trimmed+" 熱門 話題 最近")
	}
	return queries
}

func ParseMissionInspireOutput(raw string) (MissionInspireOutput, error) {
	payload, err := extractCopyMapJSON(raw)
	if err != nil {
		return MissionInspireOutput{}, err
	}
	var root map[string]json.RawMessage
	if err := json.Unmarshal(payload, &root); err != nil {
		return MissionInspireOutput{}, err
	}
	out := MissionInspireOutput{
		Label:       firstJSONString(root, "label", "title", "mission_label"),
		SeedQuery:   firstJSONString(root, "seedQuery", "seed_query", "seed", "keywords"),
		Brief:       firstJSONString(root, "brief", "description", "goal"),
		TrendReason: firstJSONString(root, "trendReason", "trend_reason", "reason"),
	}
	if out.Label == "" || out.SeedQuery == "" || out.Brief == "" {
		return MissionInspireOutput{}, fmt.Errorf("missing label, seedQuery, or brief")
	}
	if rawKW, ok := root["trendKeywords"]; ok {
		out.TrendKeywords = parseFlexibleStringList(rawKW)
	}
	if len(out.TrendKeywords) == 0 {
		if rawKW, ok := root["trend_keywords"]; ok {
			out.TrendKeywords = parseFlexibleStringList(rawKW)
		}
	}
	return out, nil
}
