"""Parser dispatcher for doc files."""

from .markdown_parser import parse_markdown, strip_mdx
from .rst_parser import parse_rst
from .asciidoc_parser import parse_asciidoc
from .notebook_parser import convert_notebook
from .html_parser import convert_html
from .openapi_parser import convert_openapi, sniff_openapi
from .json_parser import convert_json
from .xml_parser import convert_xml
from .text_parser import parse_text
from .godot_parser import convert_godot
from .hierarchy import wire_hierarchy


# Supported extensions -> parser key
ALL_EXTENSIONS = {
    ".md": "markdown",
    ".markdown": "markdown",
    ".mdx": "markdown",  # MDX = Markdown + JSX; stripped before parsing
    ".txt": "text",
    ".rst": "rst",
    ".adoc": "asciidoc",
    ".asciidoc": "asciidoc",
    ".asc": "asciidoc",
    ".ipynb": "notebook",
    ".html": "html",
    ".htm": "html",
    ".yaml": "openapi",  # indexed only when content sniff confirms OpenAPI/Swagger
    ".yml": "openapi",
    ".json": "openapi",  # OpenAPI specs get full treatment; plain JSON falls back to json parser
    ".jsonc": "json",
    ".xml": "xml",
    ".svg": "xml",
    ".xhtml": "xml",
    ".tscn": "godot",
    ".tres": "godot",
}


def preprocess_content(content: str, doc_path: str) -> str:
    """Preprocess file content before parsing and storage.

    Converts structured formats to Markdown so that parse_file() can use the
    Markdown parser uniformly:
    - .mdx → clean Markdown via strip_mdx() (removes frontmatter, imports, JSX)
    - .ipynb / .html → Markdown via notebook/HTML converters
    - .xml / .svg / .xhtml → Markdown via XML converter
    - .jsonc → Markdown via JSON converter (JSONC comments stripped)
    - .json (OpenAPI/Swagger) → Markdown via OpenAPI converter
    - .json (plain) → Markdown via JSON converter
    - .yaml / .yml (OpenAPI/Swagger) → Markdown via OpenAPI converter
    - All other formats → returned unchanged

    Args:
        content: Raw file content.
        doc_path: Relative file path (used to detect extension).

    Returns:
        Content ready for parse_file() and for storage as the raw file.
    """
    import os
    ext = os.path.splitext(doc_path)[1].lower()
    if ext == ".mdx":
        return strip_mdx(content)
    if ext == ".ipynb":
        return convert_notebook(content)
    if ext in (".html", ".htm"):
        return convert_html(content)
    if ext in (".xml", ".svg", ".xhtml"):
        return convert_xml(content, doc_path)
    if ext in (".tscn", ".tres"):
        return convert_godot(content, doc_path)
    if ext == ".jsonc":
        return convert_json(content, doc_path)
    if sniff_openapi(content, ext):
        return convert_openapi(content)
    if ext == ".json":
        return convert_json(content, doc_path)
    return content


def parse_file(content: str, doc_path: str, repo: str) -> list:
    """Parse a document file into Section objects with hierarchy wired.

    Args:
        content: Raw file content (already preprocessed by preprocess_content).
        doc_path: Relative file path (used in IDs and section metadata).
        repo: Repository identifier.

    Returns:
        List of Section objects with parent_id/children populated.
    """
    import os
    _, ext = os.path.splitext(doc_path)
    ext = ext.lower()
    doc_type = ALL_EXTENSIONS.get(ext, "text")

    if doc_type == "markdown":
        # .mdx already stripped by preprocess_content(); parse directly
        sections = parse_markdown(content, doc_path, repo)
    elif doc_type == "rst":
        sections = parse_rst(content, doc_path, repo)
    elif doc_type == "asciidoc":
        sections = parse_asciidoc(content, doc_path, repo)
    elif doc_type in ("notebook", "html"):
        # content already preprocessed to markdown by preprocess_content()
        sections = parse_markdown(content, doc_path, repo)
    elif doc_type == "openapi":
        # content is preprocessed markdown if OpenAPI; raw YAML/JSON otherwise
        # Only parse if it looks like converted markdown (starts with a heading)
        if content.lstrip().startswith("# "):
            sections = parse_markdown(content, doc_path, repo)
        else:
            sections = []
    elif doc_type in ("json", "xml", "godot"):
        # content already preprocessed to markdown by preprocess_content()
        if content.lstrip().startswith("# "):
            sections = parse_markdown(content, doc_path, repo)
        else:
            sections = []
    else:
        sections = parse_text(content, doc_path, repo)

    return wire_hierarchy(sections)
