package regras

import (
	"regexp"
	"strings"
	"unicode/utf8"
)

var reControle = regexp.MustCompile(`[\x00-\x1F\x7F]`)

// CorrigirLatin1 normaliza textos do banco: preserva UTF-8 válido, repara mojibake
// e converte bytes Latin-1 legados quando necessário.
func CorrigirLatin1(s string) string {
	if s == "" {
		return s
	}
	s = SanitizarControles(s)
	if utf8.ValidString(s) {
		return repararMojibakeSeNecessario(s)
	}
	return latin1ParaUTF8(s)
}

func repararMojibakeSeNecessario(s string) string {
	if !strings.ContainsAny(s, "ÃÂ�") {
		return s
	}
	cur := s
	for pass := 0; pass < 5; pass++ {
		next, ok := latin1Roundtrip(cur)
		if !ok || next == cur {
			break
		}
		cur = SanitizarControles(next)
		if !strings.ContainsAny(cur, "ÃÂ�") {
			return cur
		}
	}
	return cur
}

func latin1Roundtrip(s string) (string, bool) {
	if s == "" {
		return s, false
	}
	b := make([]byte, len(s))
	for i, r := range s {
		if r > 0xFF {
			return s, false
		}
		b[i] = byte(r)
	}
	if !utf8.Valid(b) {
		return s, false
	}
	return string(b), true
}

func latin1ParaUTF8(s string) string {
	runes := make([]rune, len(s))
	for i, b := range []byte(s) {
		runes[i] = rune(b)
	}
	return SanitizarControles(string(runes))
}

func SanitizarControles(s string) string {
	s = reControle.ReplaceAllString(s, "")
	if !utf8.ValidString(s) {
		return strings.ToValidUTF8(s, "")
	}
	return s
}

func SanitizarMapa(m map[string]string) map[string]string {
	out := make(map[string]string, len(m))
	for k, v := range m {
		out[k] = CorrigirLatin1(v)
	}
	return out
}

func StripTags(s string) string {
	re := regexp.MustCompile(`<[^>]*>`)
	return re.ReplaceAllString(s, "")
}

func PrimeiroEmailJSON(email string) string {
	email = strings.TrimSpace(email)
	if email == "" || email[0] != '[' {
		return email
	}
	re := regexp.MustCompile(`"([^"]+@[^"]+)"`)
	if m := re.FindStringSubmatch(email); len(m) > 1 {
		return m[1]
	}
	return email
}

func telefoneUtil(t string) bool {
	t = strings.TrimSpace(t)
	if t == "" || t == "," || t == "0" {
		return false
	}
	digitos := 0
	for _, r := range t {
		if r >= '0' && r <= '9' {
			digitos++
		}
	}
	return digitos >= 8
}

// TelefoneContato extrai o primeiro telefone útil de campos JSON ou texto.
func TelefoneContato(telefone, whatsapp, celular string) string {
	for _, raw := range []string{telefone, whatsapp, celular} {
		raw = strings.TrimSpace(raw)
		if raw == "" {
			continue
		}
		if raw[0] == '[' {
			if t := PrimeiroTelefoneJSON(raw); telefoneUtil(t) {
				return t
			}
			continue
		}
		if telefoneUtil(raw) {
			return raw
		}
	}
	return ""
}

func PrimeiroTelefoneJSON(telefone string) string {
	telefone = strings.TrimSpace(telefone)
	if telefone == "" || telefone == "," {
		return ""
	}
	if telefone[0] != '[' {
		return telefone
	}
	re := regexp.MustCompile(`"([^"]+)"`)
	for _, m := range re.FindAllStringSubmatch(telefone, -1) {
		if len(m) > 1 {
			v := strings.TrimSpace(m[1])
			if v != "" && v != "," && v != "0" {
				return v
			}
		}
	}
	return ""
}
