package placement

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

type ResearchMap struct {
	AudienceSummary string   `json:"audienceSummary"`
	ContentGoal     string   `json:"contentGoal"`
	Questions       []string `json:"questions"`
	Pillars         []string `json:"pillars"`
	Exclusions      []string `json:"exclusions"`
}

type ResearchMapInput struct {
	Label          string
	SeedQuery      string
	Brief          string
	ProductContext string
}

var researchMapFenceRE = regexp.MustCompile("(?s)```(?:json)?\\s*([\\s\\S]*?)```")

func BuildResearchMapSystemPrompt() string {
	return strings.TrimSpace(`你是 Threads（脆）產品置入研究顧問。目標是幫品牌找到「近期發文、作者有需求、現在留言還來得及自然推薦產品」的貼文。

規則：
1. questions 與 pillars 會直接拿去 Threads 搜尋——每句 5～20 字，像真人求助
2. questions 至少 5 個；pillars 至少 4 個；exclusions 至少 4 個
3. contentGoal 要寫：找到近期發文且可自然留言置入的貼文
4. 全部繁體中文，貼近台灣 Threads
5. 只回傳一個 JSON：audienceSummary, contentGoal, questions, pillars, exclusions`)
}

func BuildResearchMapUserPrompt(in ResearchMapInput) 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))
	b.WriteString("\n【產品置入】\n")
	product := FormatProductContextForPrompt(in.ProductContext)
	if product == "" {
		product = "（尚未填寫）"
	}
	b.WriteString(product)
	b.WriteString("\n\n請產出研究地圖 JSON。")
	return b.String()
}

func ParseResearchMapOutput(raw string) (ResearchMap, error) {
	payload, err := extractResearchJSONObject(raw)
	if err != nil {
		return ResearchMap{}, err
	}
	var out ResearchMap
	if err := json.Unmarshal(payload, &out); err != nil {
		return ResearchMap{}, fmt.Errorf("parse research map json: %w", err)
	}
	out.AudienceSummary = strings.TrimSpace(out.AudienceSummary)
	out.ContentGoal = strings.TrimSpace(out.ContentGoal)
	out.Questions = cleanStringList(out.Questions)
	out.Pillars = cleanStringList(out.Pillars)
	out.Exclusions = cleanStringList(out.Exclusions)
	if out.AudienceSummary == "" && len(out.Questions) == 0 {
		return ResearchMap{}, fmt.Errorf("research map missing audience or questions")
	}
	return out, nil
}

func cleanStringList(items []string) []string {
	out := make([]string, 0, len(items))
	seen := map[string]struct{}{}
	for _, item := range items {
		item = strings.TrimSpace(item)
		if item == "" {
			continue
		}
		if _, ok := seen[item]; ok {
			continue
		}
		seen[item] = struct{}{}
		out = append(out, item)
	}
	return out
}

func extractResearchJSONObject(raw string) ([]byte, error) {
	raw = strings.TrimSpace(raw)
	if m := researchMapFenceRE.FindStringSubmatch(raw); len(m) == 2 {
		raw = strings.TrimSpace(m[1])
	}
	start := strings.Index(raw, "{")
	end := strings.LastIndex(raw, "}")
	if start < 0 || end <= start {
		return nil, fmt.Errorf("research map output missing json object")
	}
	return []byte(raw[start : end+1]), nil
}
