"""Heading-hierarchy check for Markdown / Quarto / HTML files."""

import re
from pathlib import Path


def check_headings(path) -> list[dict]:
    """Scan a file for skipped heading levels (e.g., ## followed by ####).

    Skipping levels breaks the document outline relied on by screen readers
    and violates WCAG 2.1 SC 1.3.1 (Info and Relationships) and 2.4.10
    (Section Headings). Supported extensions: ``.md``, ``.qmd``, ``.Rmd``,
    ``.html``.

    Returns a list of dicts with keys ``line``, ``level``, ``text``,
    ``issue``. Empty list if the document has a clean hierarchy.
    """
    path = Path(path)
    if not path.exists():
        raise FileNotFoundError(f"File not found: {path}")

    if path.suffix.lower() == ".html":
        headings = _parse_headings_html(path)
    else:
        headings = _parse_headings_md(path)

    return [
        {**h, "issue": f"Level skip from h{headings[i-1]['level']} to h{h['level']}"}
        for i, h in enumerate(headings)
        if i > 0 and h["level"] - headings[i - 1]["level"] > 1
    ]


def _parse_headings_md(path):
    text = path.read_text(encoding="utf-8")
    in_fence = False
    out = []
    for i, line in enumerate(text.splitlines(), start=1):
        if line.startswith("```"):
            in_fence = not in_fence
            continue
        if in_fence:
            continue
        m = re.match(r"^(#{1,6})\s+(.+)$", line)
        if m:
            out.append({"line": i, "level": len(m.group(1)), "text": m.group(2)})
    return out


def _parse_headings_html(path):
    raw = path.read_text(encoding="utf-8")
    pattern = re.compile(r"<h([1-6])[^>]*>(.*?)</h[1-6]>", re.IGNORECASE | re.DOTALL)
    return [
        {
            "line":  i,
            "level": int(m.group(1)),
            "text":  re.sub(r"<[^>]+>", "", m.group(2)).strip(),
        }
        for i, m in enumerate(pattern.finditer(raw), start=1)
    ]
