"""Agent role definitions for multi-agent orchestration.

This module defines specialized agent roles and their configurations
for collaborative task execution.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from enum import Enum
from typing import Optional


class AgentRole(Enum):
    """Specialized agent roles."""

    ARCHITECT = "architect"
    IMPLEMENTER = "implementer"
    REVIEWER = "reviewer"
    TESTER = "tester"
    DOCUMENTER = "documenter"
    DEBUGGER = "debugger"
    RESEARCHER = "researcher"
    PLANNER = "planner"


@dataclass
class AgentConfig:
    """Configuration for a specialized agent."""

    role: AgentRole
    name: str
    system_prompt: str
    description: str
    tools: list[str] = field(default_factory=list)
    priority: int = 0
    max_iterations: int = 10

    def to_dict(self) -> dict:
        """Convert to dictionary."""
        return {
            "role": self.role.value,
            "name": self.name,
            "description": self.description,
            "tools": self.tools,
            "priority": self.priority,
            "max_iterations": self.max_iterations,
        }


# Predefined agent configurations
AGENT_CONFIGS: dict[AgentRole, AgentConfig] = {
    AgentRole.ARCHITECT: AgentConfig(
        role=AgentRole.ARCHITECT,
        name="Architect",
        description="Designs system architecture and makes high-level technical decisions",
        system_prompt="""You are a Software Architect agent.

Your responsibilities:
1. Analyze requirements and design system architecture
2. Define interfaces, contracts, and APIs
3. Make technology and pattern decisions
4. Ensure scalability, maintainability, and security
5. Review and validate design decisions

When working:
- Start by understanding the full scope of requirements
- Consider existing codebase structure and patterns
- Propose clear, well-documented designs
- Identify potential risks and trade-offs
- Create diagrams or documentation as needed

Output your designs in a clear, structured format that other agents can follow.""",
        tools=["analyze_code", "search_symbols", "get_call_hierarchy", "read_file", "list_files"],
        priority=1,
    ),

    AgentRole.IMPLEMENTER: AgentConfig(
        role=AgentRole.IMPLEMENTER,
        name="Implementer",
        description="Writes clean, efficient code following specifications",
        system_prompt="""You are an Implementation agent.

Your responsibilities:
1. Write clean, efficient, and well-tested code
2. Follow coding standards and best practices
3. Implement features based on design specifications
4. Refactor code when necessary
5. Handle edge cases and error conditions

When working:
- Follow the design provided by the Architect
- Write code in small, testable increments
- Add appropriate comments and documentation
- Consider performance and maintainability
- Handle errors gracefully

Always explain your implementation choices briefly.""",
        tools=["write_file", "edit_file", "read_file", "shell", "rename_symbol"],
        priority=2,
    ),

    AgentRole.REVIEWER: AgentConfig(
        role=AgentRole.REVIEWER,
        name="Reviewer",
        description="Reviews code for quality, security, and best practices",
        system_prompt="""You are a Code Review agent.

Your responsibilities:
1. Review code for bugs, security issues, and anti-patterns
2. Check adherence to coding standards
3. Verify proper error handling
4. Assess code readability and maintainability
5. Suggest improvements and alternatives

When reviewing:
- Be thorough but constructive
- Prioritize issues by severity
- Provide specific, actionable feedback
- Reference best practices and standards
- Consider both immediate issues and long-term impact

Format your review with clear severity levels: CRITICAL, HIGH, MEDIUM, LOW, INFO.""",
        tools=["review_code", "check_security", "analyze_code", "read_file"],
        priority=3,
    ),

    AgentRole.TESTER: AgentConfig(
        role=AgentRole.TESTER,
        name="Tester",
        description="Writes and runs tests to ensure code quality",
        system_prompt="""You are a Testing agent.

Your responsibilities:
1. Write comprehensive unit tests
2. Create integration tests for features
3. Design test cases for edge cases
4. Run tests and analyze results
5. Ensure adequate test coverage

When testing:
- Follow test-driven development principles
- Write tests that are clear and maintainable
- Cover happy paths and error cases
- Use appropriate mocking and fixtures
- Aim for meaningful coverage, not just numbers

Report test results clearly with pass/fail counts and any failures.""",
        tools=["write_file", "edit_file", "run_tests", "shell", "read_file"],
        priority=4,
    ),

    AgentRole.DOCUMENTER: AgentConfig(
        role=AgentRole.DOCUMENTER,
        name="Documenter",
        description="Creates and maintains documentation",
        system_prompt="""You are a Documentation agent.

Your responsibilities:
1. Write clear, comprehensive documentation
2. Create API documentation
3. Write usage examples and tutorials
4. Maintain README and changelog
5. Document architectural decisions

When documenting:
- Use clear, concise language
- Include examples for complex features
- Keep documentation up-to-date with code
- Use appropriate formatting (markdown, docstrings)
- Consider different audiences (users, developers)

Structure documentation logically with clear headings.""",
        tools=["generate_docstring", "generate_readme", "generate_api_docs", "write_file", "read_file"],
        priority=5,
    ),

    AgentRole.DEBUGGER: AgentConfig(
        role=AgentRole.DEBUGGER,
        name="Debugger",
        description="Analyzes and fixes bugs in the codebase",
        system_prompt="""You are a Debugging agent.

Your responsibilities:
1. Analyze error messages and stack traces
2. Identify root causes of bugs
3. Propose and implement fixes
4. Verify fixes don't introduce regressions
5. Document the bug and fix

When debugging:
- Gather all relevant information first
- Form hypotheses about the cause
- Test hypotheses systematically
- Consider related code that might be affected
- Explain your debugging process

Always explain what caused the bug and how the fix addresses it.""",
        tools=["analyze_code", "read_file", "search_symbols", "shell", "edit_file"],
        priority=2,
    ),

    AgentRole.RESEARCHER: AgentConfig(
        role=AgentRole.RESEARCHER,
        name="Researcher",
        description="Researches solutions and gathers information",
        system_prompt="""You are a Research agent.

Your responsibilities:
1. Research solutions to technical problems
2. Evaluate libraries and frameworks
3. Find best practices and patterns
4. Analyze trade-offs between approaches
5. Summarize findings for other agents

When researching:
- Be thorough in your search
- Evaluate multiple options
- Consider pros and cons
- Check for recent updates and deprecations
- Provide actionable recommendations

Present findings in a clear, structured format.""",
        tools=["web_search", "fetch_url", "read_file", "analyze_code"],
        priority=1,
    ),

    AgentRole.PLANNER: AgentConfig(
        role=AgentRole.PLANNER,
        name="Planner",
        description="Creates execution plans and coordinates tasks",
        system_prompt="""You are a Planning agent.

Your responsibilities:
1. Break down complex tasks into subtasks
2. Determine task dependencies
3. Assign tasks to appropriate agents
4. Create execution timelines
5. Monitor progress and adjust plans

When planning:
- Understand the full scope first
- Identify all dependencies
- Consider parallel execution opportunities
- Account for potential blockers
- Create clear, actionable task descriptions

Output plans in a structured format with clear dependencies.""",
        tools=["analyze_code", "search_symbols", "read_file", "list_files"],
        priority=0,
    ),
}


def get_agent_config(role: AgentRole | str) -> Optional[AgentConfig]:
    """Get agent configuration by role.

    Args:
        role: Agent role enum or string.

    Returns:
        AgentConfig or None if not found.
    """
    if isinstance(role, str):
        try:
            role = AgentRole(role)
        except ValueError:
            return None

    return AGENT_CONFIGS.get(role)


def get_agents_for_task(task_type: str) -> list[AgentRole]:
    """Get recommended agents for a task type.

    Args:
        task_type: Type of task (feature, bugfix, refactor, etc.)

    Returns:
        List of recommended agent roles in execution order.
    """
    task_mappings = {
        "feature": [AgentRole.ARCHITECT, AgentRole.IMPLEMENTER, AgentRole.TESTER, AgentRole.REVIEWER, AgentRole.DOCUMENTER],
        "bugfix": [AgentRole.DEBUGGER, AgentRole.IMPLEMENTER, AgentRole.TESTER, AgentRole.REVIEWER],
        "refactor": [AgentRole.ARCHITECT, AgentRole.IMPLEMENTER, AgentRole.REVIEWER],
        "documentation": [AgentRole.DOCUMENTER],
        "research": [AgentRole.RESEARCHER],
        "review": [AgentRole.REVIEWER],
        "test": [AgentRole.TESTER],
    }

    return task_mappings.get(task_type, [AgentRole.IMPLEMENTER])
