"""Utilities for parsing markdown files with YAML frontmatter."""

import re
from pathlib import Path
from typing import Any, Dict, Tuple

import yaml


def validate_file_size(file_path: Path, max_size: int = 10 * 1024 * 1024) -> None:
    """Validate that a file is within size limits.

    Args:
        file_path: Path to the file to validate
        max_size: Maximum allowed file size in bytes (default: 10MB)

    Raises:
        ValueError: If file exceeds size limit
        FileNotFoundError: If file doesn't exist
    """
    if not file_path.exists():
        raise FileNotFoundError(f"File not found: {file_path}")

    file_size = file_path.stat().st_size
    if file_size > max_size:
        raise ValueError(
            f"File too large: {file_path} ({file_size} bytes, max: {max_size} bytes)"
        )


def validate_content_safety(content: str) -> None:
    """Validate content for potentially dangerous patterns.

    Args:
        content: The content string to validate

    Raises:
        ValueError: If dangerous patterns are detected
    """
    # Check content length
    max_length = 5 * 1024 * 1024  # 5MB
    if len(content) > max_length:
        raise ValueError(
            f"Content too large: {len(content)} characters (max: {max_length})"
        )

    # Check for potentially dangerous patterns
    dangerous_patterns = [
        r"<script[^>]*>.*?</script>",
        r"javascript:",
        r"data:text/html",
        r"eval\s*\(",
        r"exec\s*\(",
        r"import\s+os",
        r"import\s+subprocess",
        r"__import__\s*\(",
    ]

    for pattern in dangerous_patterns:
        if re.search(pattern, content, re.IGNORECASE | re.DOTALL):
            raise ValueError(f"Potentially dangerous content detected: {pattern}")


def validate_yaml_complexity(yaml_content: str) -> None:
    """Validate YAML content for complexity limits.

    Args:
        yaml_content: YAML content string to validate

    Raises:
        ValueError: If YAML is too complex
    """
    # Check for deeply nested structures
    max_depth = 10
    current_depth = 0
    max_current_depth = 0

    for line in yaml_content.split("\n"):
        # Count leading spaces to determine depth
        leading_spaces = len(line) - len(line.lstrip())
        if leading_spaces > 0:
            current_depth = leading_spaces // 2  # Assuming 2-space indentation
            max_current_depth = max(max_current_depth, current_depth)

    if max_current_depth > max_depth:
        raise ValueError(
            f"YAML too deeply nested: {max_current_depth} levels (max: {max_depth})"
        )

    # Check for excessive content
    max_yaml_length = 50 * 1024  # 50KB
    if len(yaml_content) > max_yaml_length:
        raise ValueError(
            f"YAML content too large: {len(yaml_content)} bytes "
            f"(max: {max_yaml_length})"
        )


def parse_frontmatter(content: str) -> Tuple[Dict[str, Any], str]:
    """Parse YAML frontmatter from markdown content.

    Args:
        content: The markdown content potentially containing frontmatter

    Returns:
        A tuple of (frontmatter_dict, markdown_content)
        If no frontmatter is found, returns ({}, content)
    """
    # Validate content safety first
    validate_content_safety(content)

    # Check if content starts with frontmatter delimiter
    if not content.strip().startswith("---"):
        return {}, content

    # Split content by frontmatter delimiters
    parts = content.split("---", 2)

    if len(parts) < 3:
        # No valid frontmatter found
        return {}, content

    # parts[0] should be empty (before first ---)
    # parts[1] contains the YAML frontmatter
    # parts[2] contains the markdown content

    try:
        yaml_content = parts[1].strip()

        # Validate YAML complexity before parsing
        validate_yaml_complexity(yaml_content)

        frontmatter = yaml.safe_load(yaml_content)
        markdown_content = parts[2].strip()

        # Ensure frontmatter is a dict
        if not isinstance(frontmatter, dict):
            return {}, content

        return frontmatter, markdown_content

    except yaml.YAMLError:
        # Invalid YAML in frontmatter, return original content
        return {}, content


def parse_agents_with_frontmatter(content: str) -> list[dict[str, Any]]:
    """Parse agents from markdown content with frontmatter support.

    This function supports both the old regex-based format and the new
    frontmatter format for backward compatibility.

    Args:
        content: The markdown content containing agent definitions

    Returns:
        List of agent dictionaries with parsed metadata
    """
    agents = []

    # First check if this is a single file with frontmatter
    frontmatter, markdown_content = parse_frontmatter(content)

    if frontmatter:
        # Single agent file with frontmatter
        agent = {
            "name": frontmatter.get("name", ""),
            "role": frontmatter.get("role", ""),
            "scope": frontmatter.get("scope", ""),
            "dependencies": frontmatter.get("dependencies", []),
            "output_format": frontmatter.get("output_format"),
            "constraints": frontmatter.get("constraints"),
            "raw_markdown": markdown_content,
        }
        agents.append(agent)
    else:
        # Fall back to regex-based parsing for backward compatibility
        # Split by level-3 headings (### AgentName ...)
        parts = re.split(r"^### +", content, flags=re.MULTILINE)

        # First element before first heading is typically empty/intro, skip it
        for part in parts[1:]:
            lines = part.split("\n")
            name_line = lines[0].strip()
            body = "\n".join(lines[1:])

            # Parse the old format
            agent = _parse_agent_content_legacy(name_line, body)
            agents.append(agent)

    return agents


def _parse_agent_content_legacy(name: str, content: str) -> Dict[str, Any]:
    """Parse agent content using the legacy regex-based format."""
    lines = content.split("\n")
    role = ""
    scope = ""
    dependencies = []

    for line in lines:
        if line.startswith("**ROLE**:"):
            role = line.replace("**ROLE**:", "").strip()
        elif line.startswith("**SCOPE**:"):
            scope = line.replace("**SCOPE**:", "").strip()
        elif line.startswith("**DEPENDENCIES**:"):
            deps_line = line.replace("**DEPENDENCIES**:", "").strip()
            dependencies = [d.strip() for d in deps_line.split(",") if d.strip()]

    return {
        "name": name.title(),
        "role": role,
        "scope": scope,
        "dependencies": dependencies,
        "output_format": None,
        "constraints": None,
        "raw_markdown": content,
    }


def parse_principles_with_frontmatter(content: str) -> list[dict[str, Any]]:
    """Parse principles from markdown content with frontmatter support.

    Args:
        content: The markdown content containing principle definitions

    Returns:
        List of principle dictionaries with parsed metadata
    """
    principles = []

    # First check if this is a single file with frontmatter
    frontmatter, markdown_content = parse_frontmatter(content)

    if frontmatter:
        # Single principle file with frontmatter
        principle = {
            "title": frontmatter.get("title", ""),
            "priority": frontmatter.get("priority", "medium"),
            "category": frontmatter.get("category", ""),
            "content": markdown_content,
            "subsections": frontmatter.get("subsections", []),
        }
        principles.append(principle)
    else:
        # Fall back to regex-based parsing for backward compatibility
        # Split by level-3 headings (### Principle Title)
        parts = re.split(r"^### +", content, flags=re.MULTILINE)

        for part in parts[1:]:
            lines = part.split("\n")
            title = lines[0].strip()
            body = "\n".join(lines[1:])

            principle = {
                "title": title,
                "priority": "medium",
                "category": "",
                "content": body,
                "subsections": [],
            }
            principles.append(principle)

    return principles


def parse_section_with_frontmatter(filename: str, content: str) -> dict[str, Any]:
    """Parse a section file with frontmatter metadata.

    Args:
        filename: The filename of the section (e.g., "01-core-mission.md")
        content: The markdown content with frontmatter

    Returns:
        Dictionary with section metadata and content
    """
    # Extract order number from filename
    import re

    match = re.match(r"^(\d+)-", filename)
    order = int(match.group(1)) if match else 999

    # Parse frontmatter
    frontmatter, markdown_content = parse_frontmatter(content)

    # Build section data with defaults
    section_data = {
        "filename": filename,
        "order": frontmatter.get("order_override", order),
        "title": frontmatter.get(
            "title", filename.replace(".md", "").replace("-", " ").title()
        ),
        "content": markdown_content,
        "section_type": frontmatter.get("section_type", "content"),
        "template_var": frontmatter.get("template_var"),
        "required": frontmatter.get("required", True),
        "order_override": frontmatter.get("order_override"),
    }

    return section_data
