"""
Add command for EvenAge CLI.

Adds agents and tools to existing projects.
"""

from __future__ import annotations

from pathlib import Path

import click
import yaml

from ..utils import (
    AgentNotFoundError,
    ProjectNotFoundError,
    add_worker_to_compose,
    get_template_renderer,
    print_info,
    print_success,
    validate_project_directory,
    write_file,
)


@click.group()
def add():
    """Add resources to your project (agents, tools)."""


@add.command("agent")
@click.argument("agent_name")
@click.option("--role", help="Agent role")
@click.option("--goal", help="Agent goal")
@click.option("--backstory", help="Agent backstory")
@click.option("--llm-provider", default="gemini", help="LLM provider")
@click.option("--llm-model", default="gemini-2.5-flash", help="LLM model")
def add_agent(
    agent_name: str,
    role: str | None,
    goal: str | None,
    backstory: str | None,
    llm_provider: str,
    llm_model: str,
):
    """Add a new agent to the project.
    
    Examples:
        evenage add agent summarizer
        evenage add agent analyst --role "Data Analyst" --goal "Analyze data"
    """
    # Validate agent name
    if "-" in agent_name:
        raise click.BadParameter(
            "Agent name cannot contain hyphens (-). Use underscores (_) instead.",
            param_hint="agent_name"
        )
    
    if not agent_name.replace("_", "").isalnum():
        raise click.BadParameter(
            "Agent name must contain only letters, numbers, and underscores.",
            param_hint="agent_name"
        )
    
    # Ensure we're in a project
    if not validate_project_directory(Path.cwd()):
        raise ProjectNotFoundError()

    print_info(f"Adding agent: {agent_name}")

    # Prompt for missing details
    if not role:
        role = click.prompt("Agent role")
    if not goal:
        goal = click.prompt("Agent goal")
    if not backstory:
        backstory = click.prompt("Agent backstory", default="", show_default=False)

    # Create agent files
    _create_agent_files(
        agent_name=agent_name,
        role=role,
        goal=goal,
        backstory=backstory,
        llm_provider=llm_provider,
        llm_model=llm_model,
    )

    print_success(f"Agent {agent_name} created")
    print_info(f"  Handler: agents/{agent_name}/handler.py")
    print_info(f"  Worker: workers/{agent_name}_worker.py")
    print_info("  Docker service added to docker-compose.yml")


@add.command("tool")
@click.argument("tool_name")
@click.option("--agent", help="Agent to attach tool to (default: first agent)")
@click.option("--description", help="Tool description")
def add_tool(
    tool_name: str,
    agent: str | None,
    description: str | None,
):
    """Add a new tool to an agent.
    
    Examples:
        evenage add tool calculator
        evenage add tool scraper --agent researcher
    """
    # Validate tool name
    if "-" in tool_name:
        raise click.BadParameter(
            "Tool name cannot contain hyphens (-). Use underscores (_) instead.",
            param_hint="tool_name"
        )
    
    if not tool_name.replace("_", "").isalnum():
        raise click.BadParameter(
            "Tool name must contain only letters, numbers, and underscores.",
            param_hint="tool_name"
        )
    
    # Ensure we're in a project
    if not validate_project_directory(Path.cwd()):
        raise ProjectNotFoundError()

    print_info(f"Adding tool: {tool_name}")

    # Determine target agent
    if not agent:
        with open("evenage.yml", "r", encoding="utf-8") as f:
            config = yaml.safe_load(f)
        agents = config.get("project", {}).get("agents", [])
        if not agents:
            raise AgentNotFoundError("No agents found in project")
        agent = agents[0]
        print_info(f"Attaching to agent: {agent}")

    # Prompt for description if not provided
    if not description:
        description = click.prompt("Tool description", default=f"{tool_name} tool")

    # Create tool file
    _create_tool_file(tool_name, agent, description)

    print_success(f"Tool {tool_name} created")
    print_info(f"  File: agents/{agent}/tools/{tool_name}.py")
    print_info(f"  Added to {agent} agent configuration")


def _create_agent_files(
    agent_name: str,
    role: str,
    goal: str,
    backstory: str,
    llm_provider: str,
    llm_model: str,
) -> None:
    """Create agent files and update configuration."""
    renderer = get_template_renderer()

    # Create agent directory structure
    agent_path = Path("agents") / agent_name
    tools_path = agent_path / "tools"
    agent_path.mkdir(parents=True, exist_ok=True)
    tools_path.mkdir(parents=True, exist_ok=True)

    # __init__ files
    write_file(agent_path / "__init__.py", "")
    write_file(tools_path / "__init__.py", "")

    # Determine API key env var based on provider
    api_key_vars = {
        "gemini": "GEMINI_API_KEY",
        "openai": "OPENAI_API_KEY",
        "anthropic": "ANTHROPIC_API_KEY",
        "groq": "GROQ_API_KEY",
    }
    llm_api_key_var = api_key_vars.get(llm_provider.lower(), f"{llm_provider.upper()}_API_KEY")

    # Agent configuration
    agent_context = {
        "agent_name": agent_name,
        "role": role,
        "goal": goal,
        "backstory": backstory if backstory else None,
        "llm_provider": llm_provider,
        "llm_model": llm_model,
        "llm_api_key_var": llm_api_key_var,
        "temperature": 0.7,
        "max_tokens": 2048,
        "tools": [],
        "max_iterations": 15,
        "allow_delegation": False,
        "verbose": True,
    }

    # Agent handler (use new template)
    handler_context = {
        "agent_name": agent_name,
        "agent_class": f"{agent_name.capitalize()}Agent",
        "role": role,
        "goal": goal,
        "backstory": backstory or "",
        "description": role,
        "allow_delegation": False,
        "max_iterations": 15,
        "tools": [],
    }
    if agent_name.lower() == "diagnostic":
        renderer.render_to_file("agent_diagnostic.py.j2", agent_path / "handler.py", handler_context)
    else:
        # Use new template with @actor decorator
        renderer.render_to_file("agent_handler.py.j2", agent_path / "handler.py", handler_context)

    # Worker (use new template)
    worker_context = {
        "agent_name": agent_name,
        "agent_class": f"{agent_name.capitalize()}Agent",
        "role": role,
        "goal": goal,
    }
    renderer.render_to_file(
        "agent_worker.py.j2",
        Path("workers") / f"{agent_name}_worker.py",
        worker_context,
    )

    # Update evenage.yml
    with open("evenage.yml", "r", encoding="utf-8") as f:
        config_data = yaml.safe_load(f)

    if agent_name not in config_data["project"].get("agents", []):
        config_data["project"].setdefault("agents", []).append(agent_name)

    with open("evenage.yml", "w", encoding="utf-8") as f:
        yaml.dump(config_data, f, default_flow_style=False, sort_keys=False)

    # Add worker service to docker-compose.yml
    add_worker_to_compose(Path.cwd(), agent_name)

    # Auto-register agent on message bus (if Redis is available)
    _auto_register_agent(agent_name, role, goal, backstory)


def _create_tool_file(tool_name: str, agent_name: str, description: str) -> None:
    """Create tool file and update agent configuration."""
    renderer = get_template_renderer()

    # Create tool file (use new template)
    tools_dir = Path("agents") / agent_name / "tools"
    tools_dir.mkdir(parents=True, exist_ok=True)

    tool_context = {
        "tool_name": tool_name,
        "tool_function_name": tool_name.lower().replace("-", "_"),
        "tool_description": description,
        "tool_params": "query: str",  # Default params
        "params": [{"name": "query", "description": "Input query"}]
    }
    renderer.render_to_file("tool.py.j2", tools_dir / f"{tool_name}.py", tool_context)


def _auto_register_agent(agent_name: str, role: str, goal: str, backstory: str | None) -> None:
    """Auto-register agent on message bus if Redis is available."""
    try:
        import asyncio

        from evenage.core import BackendFactory, EvenAgeConfig

        # Try to connect to Redis
        config = EvenAgeConfig()
        factory = BackendFactory(config)

        async def register():
            bus = factory.create_queue_backend()
            database = factory.create_database_backend()

            metadata = {
                "role": role,
                "goal": goal,
                "backstory": backstory or "",
                "status": "inactive",
                "tools": [],
                "allow_delegation": False,
                "max_iterations": 15
            }

            # Register on bus and database
            await bus.register_agent(agent_name, metadata)
            database.register_agent(agent_name, metadata)
            print_info("  Agent registered on message bus")

        asyncio.run(register())

    except Exception as e:
        # Redis not available or other error - not critical
        print_info(f"  Skipping auto-registration (Redis not available): {e}")

