from __future__ import annotations

"""Simple text/Markdown-like parser.

This parser is intentionally conservative and layout-agnostic: it only
tries to recognize headings (``#``, ``##``, ...) and split content into
paragraphs separated by blank lines. More advanced, layout-aware parsers
for PDF/HTML/DOCX can be added alongside this one.
"""

from typing import List

from ..core.models import DocumentNode, DocumentTree, NodeType, RawDocument
from .base import BaseParser


class TextParser(BaseParser):
    """Basic parser for plain text and Markdown-like content."""

    def supports(self, raw: RawDocument) -> bool:
        # For v0.1 we optimistically treat all documents as text unless a
        # more specific parser claims them. This keeps the system usable
        # before specialized parsers (PDF, HTML, etc.) are implemented.
        return True

    def parse(self, raw: RawDocument) -> DocumentTree:
        lines = raw.content.splitlines()

        root = DocumentNode(id=f"{raw.id}#root", node_type=NodeType.DOCUMENT, text=None, metadata={})
        current_parent = root
        seen_section = False
        paragraph_buffer: List[str] = []
        counter = 0

        def flush_paragraph() -> None:
            nonlocal counter
            if not paragraph_buffer:
                return
            text = "\n".join(paragraph_buffer).strip()
            paragraph_buffer.clear()
            if not text:
                return
            counter += 1
            node = DocumentNode(
                id=f"{raw.id}#p{counter}",
                node_type=NodeType.PARAGRAPH,
                text=text,
                metadata={},
            )
            current_parent.children.append(node)

        for line in lines:
            stripped = line.strip()
            if stripped.startswith("#"):
                # Heading line
                flush_paragraph()
                level = len(stripped) - len(stripped.lstrip("#"))
                title = stripped[level:].strip() or None
                counter += 1
                section = DocumentNode(
                    id=f"{raw.id}#s{counter}",
                    node_type=NodeType.SECTION,
                    text=title,
                    metadata={"level": level},
                )
                root.children.append(section)
                current_parent = section
                seen_section = True
            elif stripped == "":
                flush_paragraph()
            else:
                paragraph_buffer.append(line)

        flush_paragraph()

        # If we never saw a heading, keep everything under the document root.
        if not seen_section:
            current_parent = root

        return DocumentTree(root=root, metadata={"source_id": raw.id})

