package render

import (
	"fmt"
	"html"
	"regexp"
	"strings"
)

var titleTagRe = regexp.MustCompile(`(?i)<title>[^<]*</title>`)

// InjectPageMeta aplica title, description, robots, canonical, OG, Twitter e JSON-LD em HTML embarcado.
func InjectPageMeta(pageHTML string, meta PageMeta) string {
	if meta.OGImage == "" {
		meta.OGImage = OGImageURL(canonicalFromMeta(meta))
	}
	if meta.OGType == "" {
		meta.OGType = "website"
	}

	robots := "index,follow"
	if meta.NoIndex {
		robots = "noindex,nofollow"
	}

	block := buildMetaBlock(meta, robots)

	out := pageHTML
	if titleTagRe.MatchString(out) {
		out = titleTagRe.ReplaceAllString(out, "<title>"+html.EscapeString(meta.Title)+"</title>")
	}
	out = setOrReplaceMeta(out, "description", meta.Description)
	out = setOrReplaceMeta(out, "robots", robots)

	if strings.Contains(out, `rel="canonical"`) {
		out = replaceLinkRel(out, "canonical", meta.Canonical)
	} else {
		block = `<link rel="canonical" href="` + html.EscapeString(meta.Canonical) + `">` + "\n    " + block
	}

	if idx := strings.Index(strings.ToLower(out), "</head>"); idx >= 0 {
		out = out[:idx] + block + out[idx:]
	}
	return out
}

func canonicalFromMeta(meta PageMeta) string {
	if meta.Canonical != "" {
		return meta.Canonical
	}
	return "https://leadb2b.org"
}

func buildMetaBlock(meta PageMeta, robots string) string {
	var b strings.Builder
	b.WriteString("\n    <!-- LEADB2B_SEO -->\n")
	b.WriteString(`    <meta property="og:title" content="` + attrEsc(meta.Title) + `">` + "\n")
	b.WriteString(`    <meta property="og:description" content="` + attrEsc(meta.Description) + `">` + "\n")
	b.WriteString(`    <meta property="og:url" content="` + attrEsc(meta.Canonical) + `">` + "\n")
	b.WriteString(`    <meta property="og:type" content="` + attrEsc(meta.OGType) + `">` + "\n")
	b.WriteString(`    <meta property="og:locale" content="pt_BR">` + "\n")
	b.WriteString(`    <meta property="og:site_name" content="LeadB2B">` + "\n")
	b.WriteString(`    <meta property="og:image" content="` + attrEsc(meta.OGImage) + `">` + "\n")
	b.WriteString(`    <meta name="twitter:card" content="summary_large_image">` + "\n")
	b.WriteString(`    <meta name="twitter:title" content="` + attrEsc(meta.Title) + `">` + "\n")
	b.WriteString(`    <meta name="twitter:description" content="` + attrEsc(meta.Description) + `">` + "\n")
	b.WriteString(`    <meta name="twitter:image" content="` + attrEsc(meta.OGImage) + `">` + "\n")
	if meta.PrevURL != "" {
		b.WriteString(`    <link rel="prev" href="` + attrEsc(meta.PrevURL) + `">` + "\n")
	}
	if meta.NextURL != "" {
		b.WriteString(`    <link rel="next" href="` + attrEsc(meta.NextURL) + `">` + "\n")
	}
	if meta.JSONLD != "" {
		b.WriteString(`    <script type="application/ld+json">` + string(meta.JSONLD) + `</script>` + "\n")
	}
	b.WriteString("    <!-- /LEADB2B_SEO -->\n")
	return b.String()
}

func attrEsc(s string) string {
	return html.EscapeString(s)
}

func setOrReplaceMeta(htmlDoc, name, content string) string {
	re := regexp.MustCompile(`(?i)<meta\s+name="` + regexp.QuoteMeta(name) + `"[^>]*>`)
	tag := fmt.Sprintf(`<meta name="%s" content="%s">`, name, attrEsc(content))
	if re.MatchString(htmlDoc) {
		return re.ReplaceAllString(htmlDoc, tag)
	}
	if idx := strings.Index(strings.ToLower(htmlDoc), "</head>"); idx >= 0 {
		return htmlDoc[:idx] + "    " + tag + "\n" + htmlDoc[idx:]
	}
	return htmlDoc
}

func replaceLinkRel(htmlDoc, rel, href string) string {
	re := regexp.MustCompile(`(?i)<link\s+rel="` + regexp.QuoteMeta(rel) + `"[^>]*>`)
	tag := fmt.Sprintf(`<link rel="%s" href="%s">`, rel, attrEsc(href))
	if re.MatchString(htmlDoc) {
		return re.ReplaceAllString(htmlDoc, tag)
	}
	return htmlDoc
}
