"""CLI entrypoint for the AI agent."""

from pathlib import Path

import typer
from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel

from agenai.agent.config import AgentConfig
from agenai.agent.core import Agent, StepType
from agenai.agent.hooks import HookRegistry, HookEvent, HookData
from agenai.agent.tools.base import ToolRegistry

# Import built-in tools
from agenai.agent.tools.read_file import ReadFileTool
from agenai.agent.tools.write_file import WriteFileTool
from agenai.agent.tools.run_command import RunCommandTool
from agenai.agent.tools.http_request import HttpRequestTool

app = typer.Typer(
    name="agenai",
    help="A modular, extensible AI agent system",
    no_args_is_help=True,
)
console = Console()


def create_default_tools() -> ToolRegistry:
    """Create a registry with default tools."""
    registry = ToolRegistry()
    registry.register(ReadFileTool())
    registry.register(WriteFileTool())
    registry.register(RunCommandTool())
    registry.register(HttpRequestTool())
    return registry


def create_verbose_hooks() -> HookRegistry:
    """Create hooks for verbose output."""
    hooks = HookRegistry()

    @hooks.on(HookEvent.STEP_START)
    def on_step_start(data: HookData) -> None:
        console.print(f"[dim]Step {data.step_number}...[/dim]")

    @hooks.on(HookEvent.TOOL_START)
    def on_tool_start(data: HookData) -> None:
        console.print(f"  [yellow]-> {data.tool_name}[/yellow]")

    @hooks.on(HookEvent.TOOL_END)
    def on_tool_end(data: HookData) -> None:
        if data.tool_result:
            status = "[green]OK[/green]" if data.tool_result.success else "[red]FAILED[/red]"
            console.print(f"  [yellow]<- {data.tool_name}[/yellow]: {status}")

    @hooks.on(HookEvent.LLM_ERROR)
    def on_llm_error(data: HookData) -> None:
        console.print(f"  [red]LLM Error: {data.error}[/red]")

    return hooks


@app.command()
def run(
    prompt: str = typer.Argument(..., help="The prompt to send to the agent"),
    model: str = typer.Option(
        "claude-sonnet-4-6",
        "--model",
        "-m",
        help="Model to use",
    ),
    max_steps: int = typer.Option(
        20,
        "--max-steps",
        help="Maximum number of agent steps",
    ),
    temperature: float = typer.Option(
        0.7,
        "--temperature",
        "-t",
        help="Sampling temperature",
    ),
    verbose: bool = typer.Option(
        False,
        "--verbose",
        "-v",
        help="Show detailed step information",
    ),
) -> None:
    """Run the agent with a single prompt."""
    config = AgentConfig(
        model=model,
        max_steps=max_steps,
        temperature=temperature,
    )

    # Load system prompt
    prompt_path = Path(__file__).parent / "prompts" / "system.txt"
    if prompt_path.exists():
        config = config.with_system_prompt_from_file(prompt_path)

    tools = create_default_tools()
    hooks = create_verbose_hooks() if verbose else None
    agent = Agent(config=config, tools=tools, hooks=hooks)

    console.print(f"\n[bold blue]Running agent with prompt:[/bold blue] {prompt}\n")

    result = agent.run(prompt)

    # Show step summary if verbose
    if verbose and result.steps:
        console.print("\n[bold]Step Summary:[/bold]")
        for i, step in enumerate(result.steps, 1):
            if step.step_type == StepType.TOOL_CALL:
                console.print(f"  {i}. [yellow]Tool:[/yellow] {step.tool_name}")
                if step.thinking:
                    console.print(f"     [dim]Thinking: {step.thinking[:80]}...[/dim]")
            elif step.step_type == StepType.FINAL_ANSWER:
                console.print(f"  {i}. [green]Final Answer[/green]")
            elif step.step_type == StepType.ERROR:
                console.print(f"  {i}. [red]Error:[/red] {step.content}")

    if result.success:
        console.print(Panel(Markdown(result.output), title="Response", border_style="green"))
    else:
        console.print(Panel(result.error or "Unknown error", title="Error", border_style="red"))

    console.print(f"\n[dim]Total tokens used: {result.total_tokens}[/dim]")


@app.command()
def chat(
    model: str = typer.Option(
        "claude-sonnet-4-6",
        "--model",
        "-m",
        help="Model to use",
    ),
    max_steps: int = typer.Option(
        20,
        "--max-steps",
        help="Maximum number of agent steps",
    ),
    verbose: bool = typer.Option(
        False,
        "--verbose",
        "-v",
        help="Show tool calls in real-time",
    ),
) -> None:
    """Start an interactive chat session with the agent."""
    config = AgentConfig(model=model, max_steps=max_steps)

    # Load system prompt
    prompt_path = Path(__file__).parent / "prompts" / "system.txt"
    if prompt_path.exists():
        config = config.with_system_prompt_from_file(prompt_path)

    tools = create_default_tools()
    hooks = create_verbose_hooks() if verbose else None
    agent = Agent(config=config, tools=tools, hooks=hooks)

    console.print("[bold green]AI Agent Chat[/bold green]")
    console.print("Type 'quit' or 'exit' to end the session.")
    console.print("Type 'reset' to start a new conversation.\n")

    while True:
        try:
            user_input = console.input("[bold blue]You:[/bold blue] ").strip()

            if not user_input:
                continue

            if user_input.lower() in ("quit", "exit"):
                console.print("[dim]Goodbye![/dim]")
                break

            if user_input.lower() == "reset":
                agent.reset()
                console.print("[dim]Conversation reset.[/dim]\n")
                continue

            result = agent.run(user_input)

            if result.success:
                console.print(f"\n[bold green]Agent:[/bold green] {result.output}\n")
            else:
                console.print(f"\n[bold red]Error:[/bold red] {result.error}\n")

        except KeyboardInterrupt:
            console.print("\n[dim]Interrupted. Goodbye![/dim]")
            break


@app.command()
def tools() -> None:
    """List available tools."""
    registry = create_default_tools()

    console.print("\n[bold]Available Tools:[/bold]\n")
    for tool_schema in registry.list():
        console.print(f"  [cyan]{tool_schema['name']}[/cyan]")
        console.print(f"    {tool_schema['description']}\n")


if __name__ == "__main__":
    app()
