package usecase

import (
	"crypto/sha256"
	"encoding/hex"
	"net/url"
	"strconv"
	"strings"

	"apps/backend/internal/module/scout/domain"
)

type classifiedPost struct {
	classification string
	score          int
	reason         string
}

func planScanTerms(brief *domain.RunBrief) []string {
	return dedupeTerms(brief.Pains, brief.Tags, brief.Periphery, []string{brief.Intent})
}

func dedupeTerms(groups ...[]string) []string {
	seen := make(map[string]struct{})
	var out []string
	for _, group := range groups {
		for _, term := range group {
			term = strings.Join(strings.Fields(strings.TrimSpace(term)), " ")
			key := strings.ToLower(term)
			if term == "" {
				continue
			}
			if _, ok := seen[key]; ok {
				continue
			}
			seen[key] = struct{}{}
			out = append(out, term)
		}
	}
	return out
}

func classifyPost(mode, text string, terms []string) classifiedPost {
	lower := strings.ToLower(text)
	signals := matchedSignals(lower, terms)
	if hasAny(lower, "giveaway", "抽獎", "follow for follow", "互追", "crypto", "賺錢") {
		return classifiedPost{domain.ClassificationNoise, 0, "noise signal"}
	}
	if mode == domain.ModeActivity {
		return classifyActivity(lower, signals)
	}
	if hasAny(lower, "dm me", "私訊我", "服務洽詢", "立即購買", "限時優惠", "團購", "業配") {
		return scored(domain.ClassificationProviderOffer, 35, signals, "provider-offer signal")
	}
	if hasAny(lower, "推薦", "求推", "有沒有推薦", "any recommendation", "what do you recommend") {
		return scored(domain.ClassificationSeekingRecommendation, 60, signals, "recommendation signal")
	}
	if strings.Contains(lower, "?") || strings.Contains(lower, "？") || hasAny(lower, "怎麼", "如何", "請問", "求助", "help") {
		return scored(domain.ClassificationSeekingHelp, 55, signals, "help-seeking signal")
	}
	return scored(domain.ClassificationDiscussion, 40, signals, "discussion signal")
}

func classifyActivity(text string, signals []string) classifiedPost {
	if hasAny(text, "dm me", "私訊我", "服務洽詢", "立即購買", "限時優惠", "團購", "業配") {
		return scored(domain.ClassificationProviderOffer, 35, signals, "provider-offer signal; recency unavailable (neutral)")
	}
	if strings.Contains(text, "?") || strings.Contains(text, "？") || hasAny(text, "請問", "怎麼", "如何", "有人知道", "求") {
		return scored(domain.ClassificationAsking, 60, signals, "asking signal; recency unavailable (neutral)")
	}
	if hasAny(text, "活動", "event", "開幕", "launch", "發布", "報名", "登記", "公告") {
		return scored(domain.ClassificationAnnouncement, 50, signals, "announcement signal; recency unavailable (neutral)")
	}
	return scored(domain.ClassificationDiscussion, 40, signals, "discussion signal; recency unavailable (neutral)")
}

func scored(classification string, base int, signals []string, label string) classifiedPost {
	score := base + len(signals)*15
	if score > 100 {
		score = 100
	}
	reason := label
	if len(signals) > 0 {
		reason += "; matched: " + strings.Join(signals, ", ")
	}
	return classifiedPost{classification, score, reason}
}

func matchedSignals(text string, terms []string) []string {
	var signals []string
	for _, term := range dedupeTerms(terms) {
		if strings.Contains(text, strings.ToLower(term)) {
			signals = append(signals, term)
		}
	}
	return signals
}

func hasAny(text string, signals ...string) bool {
	for _, signal := range signals {
		if strings.Contains(text, signal) {
			return true
		}
	}
	return false
}

func canonicalPermalink(raw string) string {
	u, err := url.Parse(strings.TrimSpace(raw))
	if err != nil || u.Host == "" {
		return ""
	}
	u.Scheme = "https"
	u.Host = strings.ToLower(u.Host)
	u.RawQuery = ""
	u.Fragment = ""
	u.Path = strings.TrimRight(u.Path, "/")
	return u.String()
}

func permalinkID(ownerUID int64, permalink string) string {
	sum := sha256.Sum256([]byte(strings.TrimSpace(permalink) + "|" + formatOwnerUID(ownerUID)))
	return "sp_" + hex.EncodeToString(sum[:])[:20]
}

func formatOwnerUID(ownerUID int64) string {
	return strconv.FormatInt(ownerUID, 10)
}
