package profanity

import (
	"strings"

	goaway "github.com/TwiN/go-away"
)

var detector *goaway.ProfanityDetector

func init() {
	combined := mergeUniqueWords(
		goaway.DefaultProfanities,
		russianProfanityFullWords,
		latinRussianProfanityFull,
	)
	detector = goaway.NewProfanityDetector().WithCustomDictionary(
		combined,
		goaway.DefaultFalsePositives,
		goaway.DefaultFalseNegatives,
	)
}

func mergeUniqueWords(parts ...[]string) []string {
	seen := make(map[string]struct{}, 768)
	out := make([]string, 0, 768)
	for _, p := range parts {
		for _, w := range p {
			if w == "" {
				continue
			}
			if _, ok := seen[w]; ok {
				continue
			}
			seen[w] = struct{}{}
			out = append(out, w)
		}
	}
	return out
}

// foldYoToE maps ё→е so dictionary entries using «е» still match nicknames typed with «ё».
func foldYoToE(s string) string {
	var b strings.Builder
	b.Grow(len(s))
	for _, r := range s {
		switch r {
		case 'ё', 'Ё':
			b.WriteRune('е')
		default:
			b.WriteRune(r)
		}
	}
	return b.String()
}

// HeroNameIsProfane: go-away (англ. + leet) + полные русские и латинские формы; две нормализации омоглифов.
func HeroNameIsProfane(name string) bool {
	folded := foldYoToE(name)
	if detector.IsProfane(folded) {
		return true
	}
	if detector.IsProfane(cyrillicHomoglyphsToLatin(folded)) {
		return true
	}
	if hasCyrillicLetter(folded) {
		if detector.IsProfane(latinAndDigitHomoglyphsToCyrillic(folded)) {
			return true
		}
	}
	return false
}

// ChatMessageIsProfane checks free-text chat lines (shorter than hero names may allow).
func ChatMessageIsProfane(s string) bool {
	if s == "" {
		return false
	}
	folded := foldYoToE(s)
	if detector.IsProfane(folded) {
		return true
	}
	if detector.IsProfane(cyrillicHomoglyphsToLatin(folded)) {
		return true
	}
	if hasCyrillicLetter(folded) {
		if detector.IsProfane(latinAndDigitHomoglyphsToCyrillic(folded)) {
			return true
		}
	}
	return false
}
