"""
Validation for ResolutionFlow tree markdown.

Validates markdown without saving, returning detailed errors with line numbers.
"""
from app.services.tree_markdown_parser import parse_markdown_to_tree, ParseError


def validate_tree_markdown(markdown: str) -> list[ParseError]:
    """Validate tree markdown and return all errors/warnings.

    This wraps the parser and adds additional semantic checks.

    Args:
        markdown: The markdown string to validate.

    Returns:
        List of ParseError objects with line, column, message, severity.
    """
    result = parse_markdown_to_tree(markdown)
    errors = list(result.errors)

    # If parsing completely failed, return early
    if result.tree_structure is None:
        return errors

    # Additional semantic validation on the parsed tree
    _validate_tree_semantics(result.tree_structure, errors)

    return errors


def _validate_tree_semantics(tree: dict, errors: list[ParseError]) -> None:
    """Run semantic checks on a parsed tree structure."""
    all_ids: set[str] = set()
    has_solution = False

    def _collect_ids(node: dict) -> None:
        nonlocal has_solution
        all_ids.add(node.get("id", ""))
        if node.get("type") == "solution":
            has_solution = True
        for child in node.get("children", []):
            _collect_ids(child)

    _collect_ids(tree)

    if not has_solution:
        errors.append(ParseError(
            line=1, column=1,
            message="Tree must have at least one solution node",
            severity="warning"
        ))

    # Check for empty required fields
    def _validate_node(node: dict) -> None:
        ntype = node.get("type", "")
        nid = node.get("id", "")

        if ntype == "decision":
            if not node.get("question", "").strip():
                errors.append(ParseError(
                    line=1, column=1,
                    message=f"Decision node '{nid}' has an empty question",
                    severity="warning"
                ))
            if not node.get("options"):
                errors.append(ParseError(
                    line=1, column=1,
                    message=f"Decision node '{nid}' has no options",
                    severity="warning"
                ))

        elif ntype == "action":
            if not node.get("title", "").strip():
                errors.append(ParseError(
                    line=1, column=1,
                    message=f"Action node '{nid}' has an empty title",
                    severity="warning"
                ))

        elif ntype == "solution":
            if not node.get("title", "").strip():
                errors.append(ParseError(
                    line=1, column=1,
                    message=f"Solution node '{nid}' has an empty title",
                    severity="warning"
                ))

        for child in node.get("children", []):
            _validate_node(child)

    _validate_node(tree)
