package domain

import "strings"

const (
	SuggestUsageInclude = "include"
	SuggestUsageExclude = "exclude"

	SuggestBasisAudience   = "audience"
	SuggestBasisPain       = "pain"
	SuggestBasisContext    = "context"
	SuggestBasisTag        = "tag"
	SuggestBasisCapability = "capability"
	SuggestBasisExclude    = "exclude"

	// 建議數量上限：清單要能一眼看完並逐條決定，不是丟一大串讓人放棄。
	MaxSuggestions     = 20
	DefaultSuggestions = 8
)

func IsSuggestionBasisKind(kind string) bool {
	switch strings.ToLower(strings.TrimSpace(kind)) {
	case SuggestBasisAudience, SuggestBasisPain, SuggestBasisContext, SuggestBasisTag, SuggestBasisCapability, SuggestBasisExclude:
		return true
	default:
		return false
	}
}

/*
WatchTermSuggestion 是一則關鍵字建議。

Reason 是必填的：使用者要逐條決定採不採用，看不到「為什麼建議這個詞」就只能全採或全不採，
那這個功能就退化成一個猜測產生器。
*/
type WatchTermSuggestion struct {
	Term      string `json:"term"`
	Reason    string `json:"reason"`
	Usage     string `json:"usage"`
	BasisKind string `json:"basis_kind,omitempty"`
	BasisText string `json:"basis_text,omitempty"`
}

func NormalizeSuggestUsage(s string) string {
	if strings.EqualFold(strings.TrimSpace(s), SuggestUsageExclude) {
		return SuggestUsageExclude
	}
	return SuggestUsageInclude
}

/*
CleanSuggestions 收掉空白與重複，丟掉沒有理由的項目，並套用數量上限。

沒有理由的項目直接丟：補一句「AI 建議」等於假裝有理由，比少一則更糟。
include 必須能在 Threads 搜到：已合規的原詞保留；過長或超過兩個 token 的先收成短詞變體，
變體也沒有才丟掉。exclude 仍用較寬的長度界線（訂閱排除詞可能較長）。
*/
func CleanSuggestions(in []WatchTermSuggestion, limit int) []WatchTermSuggestion {
	if limit <= 0 || limit > MaxSuggestions {
		limit = MaxSuggestions
	}
	out := make([]WatchTermSuggestion, 0, len(in))
	seen := map[string]bool{}
	for _, s := range in {
		term := NormalizeSearchTerm(s.Term)
		reason := strings.TrimSpace(s.Reason)
		if term == "" || reason == "" {
			continue
		}
		usage := NormalizeSuggestUsage(s.Usage)
		basisText := strings.TrimSpace(s.BasisText)
		if usage == SuggestUsageInclude {
			if !IsThreadsSearchable(term) {
				variants := SearchableTermVariants(term, true)
				if len(variants) == 0 {
					continue
				}
				if basisText == "" {
					basisText = term
				}
				term = variants[0]
			}
		} else {
			// exclude: keep broader length; still reject empty after normalize
			n := len([]rune(term))
			if n < MinTermLen || n > MaxTermLen {
				continue
			}
		}
		key := strings.ToLower(term)
		if seen[key] {
			continue
		}
		seen[key] = true
		out = append(out, WatchTermSuggestion{
			Term: term, Reason: reason, Usage: usage,
			BasisKind: strings.TrimSpace(s.BasisKind), BasisText: basisText,
		})
		if len(out) >= limit {
			break
		}
	}
	return out
}
