package core

import (
	"strings"
	"testing"
)

func TestHtmlToMarkdown(t *testing.T) {
	cases := []struct {
		name     string
		html     string
		contains string // expected substring in output (not exact match)
		exact    string // if non-empty, check trimmed exact equality
	}{
		{
			name:  "h1 heading",
			html:  "<h1>Hello World</h1>",
			exact: "# Hello World",
		},
		{
			name:  "h2 heading",
			html:  "<h2>Section</h2>",
			exact: "## Section",
		},
		{
			name:  "h3 heading",
			html:  "<h3>Sub</h3>",
			exact: "### Sub",
		},
		{
			name:  "h4 heading",
			html:  "<h4>Deep</h4>",
			exact: "#### Deep",
		},
		{
			name:  "h5 heading",
			html:  "<h5>Deeper</h5>",
			exact: "##### Deeper",
		},
		{
			name:  "h6 heading",
			html:  "<h6>Deepest</h6>",
			exact: "###### Deepest",
		},
		{
			name:     "paragraph",
			html:     "<p>Hello paragraph.</p>",
			contains: "Hello paragraph.",
		},
		{
			name:     "link",
			html:     `<a href="https://example.com">click here</a>`,
			exact:    "[click here](https://example.com)",
		},
		{
			name:     "link with no text falls back to href",
			html:     `<a href="https://example.com"></a>`,
			contains: "https://example.com",
		},
		{
			name:  "strong",
			html:  "<strong>bold text</strong>",
			exact: "**bold text**",
		},
		{
			name:  "b tag",
			html:  "<b>also bold</b>",
			exact: "**also bold**",
		},
		{
			name:  "em",
			html:  "<em>italic text</em>",
			exact: "*italic text*",
		},
		{
			name:  "i tag",
			html:  "<i>also italic</i>",
			exact: "*also italic*",
		},
		{
			name:  "code inline",
			html:  "<code>fmt.Println()</code>",
			exact: "`fmt.Println()`",
		},
		{
			name:     "pre block",
			html:     "<pre>func main() {\n  println()\n}</pre>",
			contains: "```",
		},
		{
			name:     "pre block preserves content",
			html:     "<pre>func main() {\n  println()\n}</pre>",
			contains: "func main()",
		},
		{
			name:     "unordered list",
			html:     "<ul><li>Apple</li><li>Banana</li></ul>",
			contains: "- Apple",
		},
		{
			name:     "unordered list second item",
			html:     "<ul><li>Apple</li><li>Banana</li></ul>",
			contains: "- Banana",
		},
		{
			name:     "ordered list",
			html:     "<ol><li>First</li><li>Second</li></ol>",
			contains: "1. First",
		},
		{
			name:     "ordered list second item",
			html:     "<ol><li>First</li><li>Second</li></ol>",
			contains: "1. Second",
		},
		{
			name:     "br becomes newline",
			html:     "line one<br>line two",
			contains: "\n",
		},
		{
			name:     "hr becomes dashes",
			html:     "<hr>",
			contains: "---",
		},
		{
			name:     "img with alt and src",
			html:     `<img alt="logo" src="https://example.com/logo.png">`,
			exact:    "![logo](https://example.com/logo.png)",
		},
		{
			name:     "img with empty alt",
			html:     `<img alt="" src="photo.jpg">`,
			exact:    "![](photo.jpg)",
		},
		{
			name:     "blockquote",
			html:     "<blockquote>A wise saying.</blockquote>",
			contains: "> A wise saying.",
		},
		{
			name:     "script tag skipped",
			html:     "<p>visible</p><script>alert('x')</script>",
			contains: "visible",
		},
		{
			name: "script content not in output",
			html: "<p>visible</p><script>alert('x')</script>",
			// The word alert should NOT appear
		},
		{
			name:     "style tag skipped",
			html:     "<style>body{color:red}</style><p>text</p>",
			contains: "text",
		},
		{
			name:     "noscript skipped",
			html:     "<noscript>enable js</noscript><p>main</p>",
			contains: "main",
		},
		{
			name:     "div wrapping does not add markup",
			html:     "<div><p>content</p></div>",
			contains: "content",
		},
		{
			name:     "html entities decoded",
			html:     "<p>5 &gt; 3 &amp; 1 &lt; 2</p>",
			contains: "5 > 3 & 1 < 2",
		},
		{
			name:     "multiple blank lines collapsed",
			html:     "<p>a</p><p>b</p>",
			contains: "a",
		},
		{
			name:     "nested strong inside link",
			html:     `<a href="/path"><strong>bold link</strong></a>`,
			contains: "[**bold link**](/path)",
		},
		{
			name:     "html comment skipped",
			html:     "<!-- hidden -->visible",
			contains: "visible",
		},
	}

	for _, tc := range cases {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			got := HtmlToMarkdown(tc.html)
			trimmed := strings.TrimSpace(got)

			if tc.exact != "" {
				if trimmed != tc.exact {
					t.Errorf("exact mismatch\n  got:  %q\n  want: %q", trimmed, tc.exact)
				}
			}
			if tc.contains != "" {
				if !strings.Contains(got, tc.contains) {
					t.Errorf("missing expected substring\n  got:      %q\n  expected: %q", got, tc.contains)
				}
			}

			// Special case: script content must NOT appear in output.
			if tc.name == "script content not in output" {
				if strings.Contains(got, "alert") {
					t.Errorf("script content leaked into output: %q", got)
				}
			}
		})
	}
}
