"""
GitHub Comment Parsing

Parse GitHub issue and PR comments for /groknroll commands.

Examples:
    # Parse a comment
    parser = CommentParser()
    parsed = parser.parse("Hello /groknroll fix this bug")

    if parsed.has_command:
        cmd = parsed.command
        print(f"Task: {cmd.task}")
        print(f"Agent: {cmd.agent}")

    # Simple function
    result = parse_comment("/gknr --agent plan help with tests")
"""

import re
from dataclasses import dataclass, field
from typing import Optional


@dataclass
class GroknrollCommand:
    """A parsed /groknroll command"""

    trigger: str  # "/groknroll" or "/gknr"
    task: str  # The task description
    agent: Optional[str] = None  # Optional agent name
    options: dict[str, str] = field(default_factory=dict)  # Additional options
    raw_match: str = ""  # Original matched text
    start_pos: int = 0  # Position in comment
    end_pos: int = 0  # End position in comment

    @property
    def is_valid(self) -> bool:
        """Check if command is valid (has a task)"""
        return bool(self.task.strip())


@dataclass
class ParsedComment:
    """Result of parsing a comment"""

    original: str
    has_command: bool
    command: Optional[GroknrollCommand] = None
    mentions: list[str] = field(default_factory=list)  # @mentioned users
    is_pr_comment: bool = False
    issue_number: Optional[int] = None

    @property
    def task(self) -> Optional[str]:
        """Get task from command if present"""
        return self.command.task if self.command else None

    @property
    def agent(self) -> Optional[str]:
        """Get agent from command if present"""
        return self.command.agent if self.command else None


class CommentParser:
    """
    Parser for GitHub comments

    Detects /groknroll and /gknr commands in comments,
    extracts tasks and options.

    Example:
        parser = CommentParser()

        # Parse comment with command
        parsed = parser.parse("/groknroll fix the login bug")
        assert parsed.has_command
        assert parsed.command.task == "fix the login bug"

        # Parse comment with options
        parsed = parser.parse("/groknroll --agent plan review this PR")
        assert parsed.command.agent == "plan"
    """

    # Patterns for command detection
    COMMAND_PATTERN = re.compile(
        r"(?:^|\s)(/(?:groknroll|gknr))"  # Trigger
        r"(?:\s+--agent\s+(\w+))?"  # Optional --agent
        r"(?:\s+(.+?))?(?:\n|$)",  # Task (rest of line)
        re.IGNORECASE | re.MULTILINE,
    )

    # Pattern for mentions
    MENTION_PATTERN = re.compile(r"@(\w+)")

    # Valid agent names
    VALID_AGENTS = {"build", "plan"}

    def parse(self, comment: str) -> ParsedComment:
        """
        Parse a comment for groknroll commands

        Args:
            comment: The comment text

        Returns:
            ParsedComment with extracted information
        """
        # Find mentions
        mentions = self.MENTION_PATTERN.findall(comment)

        # Find command
        match = self.COMMAND_PATTERN.search(comment)

        if not match:
            return ParsedComment(
                original=comment,
                has_command=False,
                mentions=mentions,
            )

        trigger = match.group(1).lower()
        agent = match.group(2)
        task = match.group(3) or ""

        # Validate agent
        if agent and agent.lower() not in self.VALID_AGENTS:
            agent = None

        command = GroknrollCommand(
            trigger=trigger,
            task=task.strip(),
            agent=agent.lower() if agent else None,
            raw_match=match.group(0),
            start_pos=match.start(),
            end_pos=match.end(),
        )

        return ParsedComment(
            original=comment,
            has_command=True,
            command=command,
            mentions=mentions,
        )

    def extract_all_commands(self, comment: str) -> list[GroknrollCommand]:
        """
        Extract all commands from a comment

        Args:
            comment: The comment text

        Returns:
            List of GroknrollCommand objects
        """
        commands = []

        for match in self.COMMAND_PATTERN.finditer(comment):
            trigger = match.group(1).lower()
            agent = match.group(2)
            task = match.group(3) or ""

            if agent and agent.lower() not in self.VALID_AGENTS:
                agent = None

            command = GroknrollCommand(
                trigger=trigger,
                task=task.strip(),
                agent=agent.lower() if agent else None,
                raw_match=match.group(0),
                start_pos=match.start(),
                end_pos=match.end(),
            )
            commands.append(command)

        return commands

    def is_groknroll_command(self, text: str) -> bool:
        """
        Check if text contains a groknroll command

        Args:
            text: Text to check

        Returns:
            True if contains command
        """
        return bool(self.COMMAND_PATTERN.search(text))


def parse_comment(comment: str) -> ParsedComment:
    """
    Parse a GitHub comment for groknroll commands

    Args:
        comment: The comment text

    Returns:
        ParsedComment with extracted information

    Example:
        result = parse_comment("/groknroll fix bug #123")
        if result.has_command:
            print(result.command.task)  # "fix bug #123"
    """
    parser = CommentParser()
    return parser.parse(comment)


def extract_task(comment: str) -> Optional[str]:
    """
    Extract task from a comment

    Args:
        comment: The comment text

    Returns:
        Task string or None
    """
    parsed = parse_comment(comment)
    return parsed.task


def has_groknroll_command(comment: str) -> bool:
    """
    Check if comment has a groknroll command

    Args:
        comment: The comment text

    Returns:
        True if contains /groknroll or /gknr
    """
    parser = CommentParser()
    return parser.is_groknroll_command(comment)
