package viral

import (
	"strings"

	missionentity "haixun-backend/internal/model/copy_mission/domain/entity"
	accountentity "haixun-backend/internal/model/threads_account/domain/entity"
)

// ExcludedKnownAccountUsernames returns usernames marked excluded in cross-mission memory.
func ExcludedKnownAccountUsernames(known map[string]accountentity.KnownAccountProfile) []string {
	if len(known) == 0 {
		return nil
	}
	out := make([]string, 0)
	seen := map[string]struct{}{}
	for key, item := range known {
		if item.Status != accountentity.KnownAccountStatusExcluded {
			continue
		}
		user := strings.TrimSpace(key)
		if user == "" {
			continue
		}
		lower := strings.ToLower(user)
		if _, ok := seen[lower]; ok {
			continue
		}
		seen[lower] = struct{}{}
		out = append(out, user)
	}
	return out
}

// ApplyKnownAccountMemory applies cross-mission memory to freshly merged similar
// accounts: inherit excluded status and boost confidence for repeat sightings.
func ApplyKnownAccountMemory(
	accounts []missionentity.SimilarAccount,
	known map[string]accountentity.KnownAccountProfile,
) []missionentity.SimilarAccount {
	if len(accounts) == 0 || len(known) == 0 {
		return accounts
	}
	out := make([]missionentity.SimilarAccount, len(accounts))
	copy(out, accounts)
	for i := range out {
		key := strings.ToLower(strings.TrimSpace(out[i].Username))
		if key == "" {
			continue
		}
		profile, ok := known[key]
		if !ok {
			continue
		}
		if profile.Status == accountentity.KnownAccountStatusExcluded {
			out[i].Status = missionentity.SimilarAccountStatusExcluded
		}
		if len(profile.Missions) >= 2 || profile.SeenCount >= 2 {
			if out[i].Confidence != "high" {
				out[i].Confidence = "high"
			}
		}
	}
	return out
}

// MergeKnownAccountsFromScan upserts similar-account sightings into the account-level
// known_accounts map.
func MergeKnownAccountsFromScan(
	prev map[string]accountentity.KnownAccountProfile,
	accounts []missionentity.SimilarAccount,
	missionID, personaID string,
	tags []string,
	now int64,
) map[string]accountentity.KnownAccountProfile {
	out := map[string]accountentity.KnownAccountProfile{}
	for key, item := range prev {
		out[key] = item
	}
	for _, acc := range accounts {
		user := strings.TrimSpace(acc.Username)
		if user == "" {
			continue
		}
		key := strings.ToLower(user)
		profile := out[key]
		if profile.FirstSeenAt == 0 {
			profile.FirstSeenAt = now
		}
		profile.LastSeenAt = now
		profile.Missions = appendUnique(profile.Missions, missionID)
		profile.PersonaIds = appendUnique(profile.PersonaIds, personaID)
		for _, tag := range tags {
			profile.Tags = appendUnique(profile.Tags, tag)
		}
		prevCount := profile.SeenCount
		if prevCount < 0 {
			prevCount = 0
		}
		eng := float64(acc.EngagementScore)
		if prevCount == 0 {
			profile.AvgEngagement = eng
		} else {
			profile.AvgEngagement = (profile.AvgEngagement*float64(prevCount) + eng) / float64(prevCount+1)
		}
		profile.SeenCount = prevCount + 1
		switch strings.TrimSpace(acc.Status) {
		case missionentity.SimilarAccountStatusExcluded:
			profile.Status = accountentity.KnownAccountStatusExcluded
		case missionentity.SimilarAccountStatusRecommended:
			if profile.Status == accountentity.KnownAccountStatusExcluded {
				profile.Status = ""
			}
		}
		out[key] = profile
	}
	return out
}

func appendUnique(items []string, value string) []string {
	value = strings.TrimSpace(value)
	if value == "" {
		return items
	}
	for _, item := range items {
		if item == value {
			return items
		}
	}
	return append(items, value)
}
