from django import template
from django.utils.html import conditional_escape, escape
from django.utils.safestring import mark_safe
import re

register = template.Library()


def _link_repl(match):
    text = match.group(1)
    url = match.group(2)
    # Allow only http/https links
    if not re.match(r"^(https?://)", url, re.IGNORECASE):
        # The whole input has already been HTML-escaped upstream.
        return text
    return (
        f'<a class="comment-link" href="{url}" '
        f'rel="nofollow noopener noreferrer" target="_blank">{text}</a>'
    )


def _format_inline(text: str) -> str:
    # code spans first
    text = re.sub(
        r"`([^`]+)`",
        # Content is already HTML-escaped by conditional_escape; avoid double-escaping
        lambda m: f"<code class=\"comment-code\">{m.group(1)}</code>",
        text,
    )
    # H1
    text = re.sub(r"^# (.+)$", r"<h1>\1</h1>", text, flags=re.MULTILINE)
    # H2
    text = re.sub(r"^## (.+)$", r"<h2>\1</h2>", text, flags=re.MULTILINE)
    # H3
    text = re.sub(r"^### (.+)$", r"<h3>\1</h3>", text, flags=re.MULTILINE)
    # H4
    text = re.sub(r"^#### (.+)$", r"<h4>\1</h4>", text, flags=re.MULTILINE)
    # H5
    text = re.sub(r"^##### (.+)$", r"<h5>\1</h5>", text, flags=re.MULTILINE)
    # H6
    text = re.sub(r"^###### (.+)$", r"<h6>\1</h6>", text, flags=re.MULTILINE)

    # bold **text**
    text = re.sub(
        r"\*\*([^*]+)\*\*",
        lambda m: f"<strong class=\"comment-strong\">{m.group(1)}</strong>",
        text,
    )
    # italic *text* or _text_
    text = re.sub(
        r"(?<!\*)\*([^*]+)\*(?!\*)",
        lambda m: f"<em class=\"comment-em\">{m.group(1)}</em>",
        text,
    )
    text = re.sub(
        r"_([^_]+)_",
        lambda m: f"<em class=\"comment-em\">{m.group(1)}</em>",
        text,
    )
    # links [text](url)
    text = re.sub(r"\[([^\]]+)\]\(([^)]+)\)", _link_repl, text)
    return text


def _format_lists(lines):
    html_lines = []
    in_ul = False
    for line in lines:
        m = re.match(r"^\s*[-*]\s+(.+)$", line)
        if m:
            if not in_ul:
                html_lines.append("<ul class=\"comment-list\">")
                in_ul = True
            html_lines.append(f"<li>{_format_inline(m.group(1))}</li>")
        else:
            if in_ul:
                html_lines.append("</ul>")
                in_ul = False
            html_lines.append(_format_inline(line))
    if in_ul:
        html_lines.append("</ul>")
    return html_lines


@register.filter(name="comment_markdown")
def comment_markdown(value: str):
    """A very small Markdown subset renderer for comments with HTML escaping.
    Supports: paragraphs, lists (- or *), **bold**, *italic* or _italic_, `code`, [text](url).
    Fenced code blocks ```...``` will render as <pre><code>.
    All HTML is escaped.
    """
    if not value:
        return ""

    text = str(value)

    # Normalize newlines
    text = text.replace("\r\n", "\n").replace("\r", "\n")

    # Escape HTML entirely first
    text = conditional_escape(text)

    # Handle fenced code blocks ```
    parts = re.split(r"```\n?", text)
    rendered = []
    for i, part in enumerate(parts):
        if i % 2 == 1:
            # inside code block
            rendered.append(f"<pre class=\"comment-pre\"><code class=\"comment-code-block\">{part}</code></pre>")
        else:
            # regular markdown in this chunk
            # Split into paragraphs by blank lines
            paragraphs = re.split(r"\n\s*\n", part)
            for p in paragraphs:
                lines = p.split("\n")
                formatted_lines = _format_lists(lines)
                html = "<br />".join(l for l in formatted_lines if l != "")
                if html.strip():
                    rendered.append(f"<p class=\"comment-paragraph\">{html}</p>")
    html_out = "\n".join(rendered)
    return mark_safe(html_out)
