defmodule Microwaveprop.MarkdownTest do
  use ExUnit.Case, async: true

  alias Microwaveprop.Markdown

  describe "headings" do
    test "renders h1" do
      assert Markdown.to_html!("# Hello") =~ "<h1>Hello</h1>"
    end

    test "renders h2 through h6" do
      for level <- 2..6 do
        hashes = String.duplicate("#", level)
        assert Markdown.to_html!("#{hashes} Title") =~ "<h#{level}>Title</h#{level}>"
      end
    end

    test "caps at h6 for excessive hashes" do
      assert Markdown.to_html!("####### Too many") =~ "<h6>"
    end
  end

  describe "paragraphs" do
    test "renders simple paragraph" do
      assert Markdown.to_html!("Hello world") =~ "<p>Hello world</p>"
    end

    test "joins multi-line paragraphs" do
      result = Markdown.to_html!("Line one\nLine two")
      assert result =~ "<p>Line one Line two</p>"
    end

    test "separates paragraphs by blank lines" do
      result = Markdown.to_html!("Para one\n\nPara two")
      assert result =~ "<p>Para one</p>"
      assert result =~ "<p>Para two</p>"
    end
  end

  describe "fenced code blocks" do
    test "renders code block" do
      md = "```\nfoo\nbar\n```"
      result = Markdown.to_html!(md)
      assert result =~ "<pre><code>foo\nbar</code></pre>"
    end

    test "renders code block with language" do
      md = "```elixir\nIO.puts(\"hi\")\n```"
      result = Markdown.to_html!(md)
      assert result =~ ~s(<code class="language-elixir">)
    end

    test "escapes HTML in code blocks" do
      md = "```\n<script>alert('xss')</script>\n```"
      result = Markdown.to_html!(md)
      assert result =~ "&lt;script&gt;"
      refute result =~ "<script>"
    end
  end

  describe "tables" do
    test "renders table with header" do
      md = "| A | B |\n|---|---|\n| 1 | 2 |"
      result = Markdown.to_html!(md)
      assert result =~ "<thead>"
      assert result =~ "<th>A</th>"
      assert result =~ "<td>1</td>"
    end
  end

  describe "lists" do
    test "renders unordered list" do
      md = "- one\n- two\n- three"
      result = Markdown.to_html!(md)
      assert result =~ "<ul>"
      assert result =~ "<li>one</li>"
      assert result =~ "<li>two</li>"
      assert result =~ "<li>three</li>"
    end

    test "renders ordered list" do
      md = "1. first\n2. second"
      result = Markdown.to_html!(md)
      assert result =~ "<ol>"
      assert result =~ "<li>first</li>"
      assert result =~ "<li>second</li>"
    end
  end

  describe "inline formatting" do
    test "renders bold with **" do
      assert Markdown.to_html!("**bold**") =~ "<strong>bold</strong>"
    end

    test "renders bold with __" do
      assert Markdown.to_html!("__bold__") =~ "<strong>bold</strong>"
    end

    test "renders italic with *" do
      assert Markdown.to_html!("*italic*") =~ "<em>italic</em>"
    end

    test "renders inline code" do
      assert Markdown.to_html!("`code`") =~ "<code>code</code>"
    end

    test "renders links" do
      assert Markdown.to_html!("[text](http://example.com)") =~ ~s(<a href="http://example.com">text</a>)
    end
  end

  describe "list continuation" do
    test "continues unordered list items with indentation" do
      md = "- item one\n  continued\n- item two"
      result = Markdown.to_html!(md)
      assert result =~ "<li>item one continued</li>"
      assert result =~ "<li>item two</li>"
    end
  end

  describe "table without separator" do
    test "renders table body only when no separator row" do
      md = "| A | B |"
      result = Markdown.to_html!(md)
      assert result =~ "<tbody>"
      refute result =~ "<thead>"
    end
  end

  describe "CRLF handling" do
    test "normalizes CRLF to LF" do
      result = Markdown.to_html!("Hello\r\nworld")
      assert result =~ "<p>Hello world</p>"
    end
  end

  describe "empty input" do
    test "handles empty string" do
      assert Markdown.to_html!("") == ""
    end
  end

  describe "horizontal rules" do
    test "renders --- as hr" do
      assert Markdown.to_html!("---") =~ "<hr />"
    end

    test "renders *** as hr" do
      assert Markdown.to_html!("***") =~ "<hr />"
    end

    test "renders ___ as hr" do
      assert Markdown.to_html!("___") =~ "<hr />"
    end
  end

  describe "HTML escaping" do
    test "escapes angle brackets in paragraphs" do
      result = Markdown.to_html!("x < y > z")
      assert result =~ "&lt;"
      assert result =~ "&gt;"
    end

    test "escapes ampersands" do
      result = Markdown.to_html!("a & b")
      assert result =~ "&amp;"
    end
  end
end
