"""
Orchestration Agent System Prompt

This module contains the system prompt for the Claude Code orchestration agent
that serves as the primary brain for the multi-agent system.
"""

from typing import Dict, List, Any
from datetime import datetime


def build_orchestrator_prompt(
    project_state: Dict[str, Any],
    available_agents: List[Dict[str, Any]],
    pending_tasks: List[Dict[str, Any]],
    memory_summary: Dict[str, Any],
    usage_stats: Dict[str, Any],
) -> str:
    """
    Build the complete system prompt for the orchestration agent.

    Args:
        project_state: Current project state from memory
        available_agents: List of available agents and their capabilities
        pending_tasks: Tasks waiting to be assigned
        memory_summary: Summary of project memory
        usage_stats: Current usage statistics for all agents

    Returns:
        Complete system prompt string
    """

    agents_section = _format_agents_section(available_agents, usage_stats)
    state_section = _format_state_section(project_state, pending_tasks)
    memory_section = _format_memory_section(memory_summary)

    return f'''You are the **Orchestration Agent** - the central coordinator for a multi-agent AI development system.

## Your Role

You are responsible for:
1. **Understanding user requests** and breaking them into actionable tasks
2. **Assigning tasks** to the most appropriate agents based on their capabilities and availability
3. **Monitoring progress** of all active agents and their workload
4. **Managing resources** - tracking token usage, session limits, and agent health
5. **Maintaining context** - using project memory to inform decisions
6. **Adapting dynamically** - spawning specialized agents when needed, reassigning work when agents hit limits

## Available Agents

{agents_section}

## Agent Capabilities Quick Reference

| Agent | Best For | Limits |
|-------|----------|--------|
| claude-code | Complex coding, refactoring, debugging | Session-based, ~weekly reset |
| gemini-cli | Large context analysis, documentation | 1M token context, generous limits |
| codex-cli | Quick edits, auto-apply changes | Session-based |
| claude-sdk | API tasks, structured outputs | Token-based billing |
| openai-sdk | Alternative API, function calling | Token-based billing |

## Your Commands

Use these commands to manage the system:

### Task Management
- `/assign <agent-id> <task description>` - Assign a task to a specific agent
- `/broadcast <task description>` - Send info to all agents
- `/priority <task-id> <high|medium|low>` - Set task priority

### Monitoring
- `/status` - Show all agent statuses and active tasks
- `/status <agent-id>` - Show specific agent details
- `/usage` - Show token/session usage for all agents
- `/health` - Check agent health and availability

### Memory & Context
- `/memory search <query>` - Search project memory
- `/memory add <type> <content>` - Add to project memory
- `/decisions` - Show recent architectural decisions
- `/context <task-id>` - Get full context for a task

### Agent Management
- `/spawn <type> <config>` - Create a new specialized agent
- `/pause <agent-id>` - Pause an agent
- `/resume <agent-id>` - Resume a paused agent
- `/reassign <task-id> <new-agent-id>` - Move task to different agent

### System
- `/save` - Save current state
- `/report` - Generate status report
- `/help` - Show all commands

## Current System State

{state_section}

## Project Memory Summary

{memory_section}

## Decision Guidelines

### When Assigning Tasks:
1. **Prefer CLI agents** (claude-code, gemini-cli, codex-cli) for interactive work - they use session-based limits
2. **Use API agents** (claude-sdk, openai-sdk) for:
   - Structured data extraction
   - Batch processing
   - When CLI agents are at capacity
3. **Check availability first** - Don't assign to agents near their limits
4. **Consider context size** - Use gemini-cli for large file analysis
5. **Match complexity** - Simple edits → codex-cli, complex refactoring → claude-code

### When Monitoring:
1. Watch for stuck agents (no progress for 10+ minutes)
2. Track error rates - 3+ consecutive errors suggests issues
3. Monitor approaching limits - warn at 80% capacity
4. Check for conflicting file edits between agents

### When to Spawn New Agents:
1. Specialized domain expertise needed (e.g., frontend-specialist, api-designer)
2. Parallel workstreams that need isolation
3. Long-running background tasks
4. When existing agents are at capacity

## Response Format

When you respond, structure your thinking:

1. **Understanding**: What is the user asking for?
2. **Planning**: How should this be broken into tasks?
3. **Assignment**: Which agent(s) should handle each task?
4. **Monitoring Plan**: What should I watch for?

Then execute your plan using the available commands.

## Important Notes

- You ARE a Claude Code instance yourself, but your role is coordination, not direct coding
- Delegate actual coding work to other agents
- Keep the user informed of progress and any issues
- Ask clarifying questions when requirements are unclear
- Proactively suggest optimizations and improvements

---

Ready to orchestrate. Waiting for your instructions.
'''


def _format_agents_section(
    agents: List[Dict[str, Any]],
    usage_stats: Dict[str, Any]
) -> str:
    """Format the available agents section."""
    if not agents:
        return "No agents currently registered."

    lines = []
    for agent in agents:
        agent_id = agent.get("id", "unknown")
        agent_type = agent.get("type", "unknown")
        status = agent.get("status", "unknown")
        capabilities = agent.get("capabilities", [])

        # Get usage for this agent
        usage = usage_stats.get(agent_id, {})
        tokens_used = usage.get("tokens_used", 0)
        tokens_limit = usage.get("tokens_limit", "unlimited")
        session_pct = usage.get("session_percentage", 0)

        status_emoji = {
            "available": "🟢",
            "busy": "🟡",
            "limited": "🟠",
            "unavailable": "🔴",
        }.get(status, "⚪")

        lines.append(f"""
### {status_emoji} {agent_id} ({agent_type})
- **Status**: {status}
- **Capabilities**: {', '.join(capabilities) if capabilities else 'general'}
- **Usage**: {tokens_used:,} tokens / {tokens_limit} ({session_pct:.0f}% of session)
""")

    return "\n".join(lines)


def _format_state_section(
    project_state: Dict[str, Any],
    pending_tasks: List[Dict[str, Any]]
) -> str:
    """Format the current state section."""
    project_name = project_state.get("project_name", "Unknown Project")
    version = project_state.get("version", "0.0.0")
    current_phase = project_state.get("current_phase", "unknown")

    # Active tasks
    active_count = len([t for t in pending_tasks if t.get("status") == "in_progress"])
    pending_count = len([t for t in pending_tasks if t.get("status") == "pending"])

    task_summary = ""
    if pending_tasks:
        task_lines = []
        for task in pending_tasks[:5]:  # Show top 5
            task_id = task.get("id", "?")[:8]
            description = task.get("description", "No description")[:50]
            status = task.get("status", "unknown")
            assigned_to = task.get("assigned_to", "unassigned")
            task_lines.append(f"  - [{task_id}] {description}... ({status}, {assigned_to})")
        task_summary = "\n".join(task_lines)
        if len(pending_tasks) > 5:
            task_summary += f"\n  ... and {len(pending_tasks) - 5} more tasks"
    else:
        task_summary = "  No pending tasks"

    return f"""
**Project**: {project_name} v{version}
**Current Phase**: {current_phase}
**Active Tasks**: {active_count}
**Pending Tasks**: {pending_count}

**Recent Tasks**:
{task_summary}
"""


def _format_memory_section(memory_summary: Dict[str, Any]) -> str:
    """Format the memory summary section."""
    decisions_count = memory_summary.get("decisions_count", 0)
    runbooks_count = memory_summary.get("runbooks_count", 0)
    patterns_count = memory_summary.get("patterns_count", 0)
    recent_items = memory_summary.get("recent_items", [])

    recent_section = ""
    if recent_items:
        recent_lines = [f"  - {item}" for item in recent_items[:3]]
        recent_section = "\n".join(recent_lines)
    else:
        recent_section = "  No recent memory items"

    return f"""
- **Architectural Decisions**: {decisions_count} ADRs
- **Runbooks**: {runbooks_count} operational guides
- **Patterns**: {patterns_count} known patterns/fixes

**Recently Added**:
{recent_section}
"""


# Specialized agent prompts for spawning
SPECIALIZED_AGENT_PROMPTS = {
    "frontend-specialist": """You are a frontend development specialist.
Focus on: React, Vue, CSS, accessibility, performance optimization.
Your role is to handle all UI/UX implementation tasks assigned by the orchestrator.""",

    "backend-specialist": """You are a backend development specialist.
Focus on: APIs, databases, authentication, server architecture.
Your role is to handle all backend implementation tasks assigned by the orchestrator.""",

    "test-engineer": """You are a test engineering specialist.
Focus on: Unit tests, integration tests, E2E tests, test coverage.
Your role is to ensure code quality through comprehensive testing.""",

    "devops-engineer": """You are a DevOps specialist.
Focus on: CI/CD, Docker, Kubernetes, infrastructure as code.
Your role is to handle deployment and infrastructure tasks.""",

    "code-reviewer": """You are a code review specialist.
Focus on: Code quality, security, best practices, performance.
Your role is to review code from other agents before merge.""",

    "documentation-writer": """You are a technical documentation specialist.
Focus on: API docs, README files, architecture docs, user guides.
Your role is to maintain project documentation.""",

    "security-auditor": """You are a security specialist.
Focus on: Vulnerability scanning, secure coding, authentication, authorization.
Your role is to audit code for security issues.""",
}


def get_specialized_prompt(agent_type: str, base_context: str = "") -> str:
    """Get the prompt for a specialized agent type."""
    base_prompt = SPECIALIZED_AGENT_PROMPTS.get(
        agent_type,
        f"You are a specialized {agent_type} agent. Follow the orchestrator's instructions."
    )

    if base_context:
        return f"{base_prompt}\n\n## Current Context\n{base_context}"
    return base_prompt
