package services

import (
	"fmt"
	"regexp"
	"strings"
)

var (
	reCodeBlock  = regexp.MustCompile("(?s)```(?:[a-zA-Z0-9]*\n)?(.*?)```")
	reInlineCode = regexp.MustCompile("`([^`\n]+)`")
	reBold       = regexp.MustCompile(`\*\*(.+?)\*\*|__(.+?)__`)
	reHeader     = regexp.MustCompile(`(?m)^#{1,6}[ \t]+(.+)$`)
	reBullet     = regexp.MustCompile(`(?m)^(\s*)[-*][ \t]+`)
	reHRSimple   = regexp.MustCompile(`(?m)^[ \t]*(-{3,}|_{3,}|\*{3,})[ \t]*\n?`)
	reLink       = regexp.MustCompile(`\[([^\]]+)\]\(([^)\s]+)\)`)
)

// FormatearParaTelegram convierte el Markdown que suele escribir la IA (##,
// **negrita**, listas con "-", ``` código ```, separadores ---) a las pocas
// etiquetas HTML que Telegram sí entiende con parse_mode=HTML (b, i, code, pre,
// a). Escapa primero cualquier < > & literal del texto original para que
// sendMessage nunca falle por HTML inválido si la IA menciona código o símbolos.
func FormatearParaTelegram(text string) string {
	// 1. Proteger bloques de código ANTES de escapar el resto, para no
	//    procesarles negrita/viñetas por accidente.
	var blocks []string
	protect := func(html string) string {
		blocks = append(blocks, html)
		return fmt.Sprintf("\x00%d\x00", len(blocks)-1)
	}
	text = reCodeBlock.ReplaceAllStringFunc(text, func(m string) string {
		sub := reCodeBlock.FindStringSubmatch(m)
		return protect("<pre>" + escapeTelegramHTML(strings.TrimSpace(sub[1])) + "</pre>")
	})
	text = reInlineCode.ReplaceAllStringFunc(text, func(m string) string {
		sub := reInlineCode.FindStringSubmatch(m)
		return protect("<code>" + escapeTelegramHTML(sub[1]) + "</code>")
	})

	// 2. Escapar el resto del texto como HTML.
	text = escapeTelegramHTML(text)

	// 3. Separadores horizontales estilo markdown (---, ___, ***) fuera.
	text = reHRSimple.ReplaceAllString(text, "")

	// 4. Negrita (antes que encabezados, para no anidar <b> si un título
	//    también trae **negrita** adentro).
	text = reBold.ReplaceAllStringFunc(text, func(m string) string {
		sub := reBold.FindStringSubmatch(m)
		inner := sub[1]
		if inner == "" {
			inner = sub[2]
		}
		return "<b>" + inner + "</b>"
	})

	// 5. Encabezados (#, ##, ###...) → negrita, sin duplicar <b> si ya la trae.
	text = reHeader.ReplaceAllStringFunc(text, func(m string) string {
		sub := reHeader.FindStringSubmatch(m)
		inner := strings.NewReplacer("<b>", "", "</b>", "").Replace(sub[1])
		return "<b>" + inner + "</b>"
	})

	// 6. Viñetas "- " o "* " al inicio de línea → "• ".
	text = reBullet.ReplaceAllString(text, "$1• ")

	// 7. Enlaces [texto](url).
	text = reLink.ReplaceAllString(text, `<a href="$2">$1</a>`)

	// 8. Restaurar bloques de código protegidos en el paso 1.
	for i, b := range blocks {
		text = strings.ReplaceAll(text, fmt.Sprintf("\x00%d\x00", i), b)
	}

	// Máximo 3 saltos de línea seguidos (Markdown suele dejar párrafos sueltos).
	for strings.Contains(text, "\n\n\n\n") {
		text = strings.ReplaceAll(text, "\n\n\n\n", "\n\n\n")
	}

	return strings.TrimSpace(text)
}
