"""
llama2a CLI - Command-line interface for running agent chains.

Usage:
    llama2a "Build a calculator app" --output ./calculator
    llama2a "Build a REST API" --model llama3:70b --output ./api --verbose
"""

import argparse
import sys
import os
from typing import Optional

from .chain import AgentChain
from .config import ChainConfig
from .events import Event


def create_parser() -> argparse.ArgumentParser:
    """Create the argument parser."""
    parser = argparse.ArgumentParser(
        prog="llama2a",
        description="Build projects using coordinated AI agents",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  llama2a "Build a todo app with Flask" --output ./todo
  llama2a "Create a CLI calculator" --model deepseek-coder-v2:16b -o ./calc
  llama2a "Build a game with pygame" --output ./game --verbose
        """,
    )
    
    parser.add_argument(
        "requirements",
        type=str,
        help="Project requirements (what to build)",
    )
    
    parser.add_argument(
        "-o", "--output",
        type=str,
        required=True,
        help="Output directory for generated files",
    )
    
    parser.add_argument(
        "-m", "--model",
        type=str,
        default="llama3:8b",
        help="Default LLM model to use (default: llama3:8b)",
    )
    
    parser.add_argument(
        "--planner-model",
        type=str,
        help="Model for the planner agent (overrides --model)",
    )
    
    parser.add_argument(
        "--coder-model",
        type=str,
        help="Model for the coder agent (overrides --model)",
    )
    
    parser.add_argument(
        "--llm-url",
        type=str,
        default="http://localhost:11434",
        help="LLM API base URL (default: http://localhost:11434)",
    )
    
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="Enable verbose output",
    )
    
    parser.add_argument(
        "--dry-run",
        action="store_true",
        help="Show what would be done without executing",
    )
    
    parser.add_argument(
        "--version",
        action="version",
        version="%(prog)s 0.1.0",
    )
    
    return parser


def print_event(event_type: Event, data: dict, verbose: bool = False) -> None:
    """Print events to console."""
    message = data.get("message", "")
    
    if event_type == Event.CHAIN_START:
        print("\n🔗 AgentChain Starting...\n")
        if verbose:
            print(f"   Requirements: {data.get('requirements', '')[:100]}...")
    
    elif event_type == Event.AGENT_START:
        agent_name = data.get("agent", "unknown")
        print(f"▶ Starting {agent_name}...")
    
    elif event_type == Event.AGENT_COMPLETE:
        agent_name = data.get("agent", "unknown")
        print(f"✓ {agent_name} complete")
    
    elif event_type == Event.TASK_START:
        task = data.get("task", {})
        task_name = task.get("name", "unknown")
        print(f"  → Task: {task_name}")
    
    elif event_type == Event.TASK_COMPLETE:
        task = data.get("task", {})
        task_name = task.get("name", "unknown")
        print(f"  ✓ {task_name}")
    
    elif event_type == Event.TASK_FAILED:
        task = data.get("task", {})
        task_name = task.get("name", "unknown")
        error = data.get("error", "unknown error")
        print(f"  ✗ {task_name}: {error}")
    
    elif event_type == Event.AGENT_ERROR:
        error = data.get("error", "unknown error")
        print(f"❌ Error: {error}")
    
    elif event_type == Event.PROGRESS:
        if verbose and message:
            print(f"  {message}")
    
    elif event_type == Event.CHAIN_COMPLETE:
        success = data.get("success", False)
        if success:
            print("\n✅ Chain completed successfully!\n")
        else:
            print("\n❌ Chain failed\n")


def main(args: Optional[list] = None) -> int:
    """Main entry point for CLI."""
    parser = create_parser()
    parsed = parser.parse_args(args)
    
    # Dry run mode
    if parsed.dry_run:
        print("Dry run mode - would execute with:")
        print(f"  Requirements: {parsed.requirements}")
        print(f"  Output: {parsed.output}")
        print(f"  Model: {parsed.model}")
        if parsed.planner_model:
            print(f"  Planner Model: {parsed.planner_model}")
        if parsed.coder_model:
            print(f"  Coder Model: {parsed.coder_model}")
        print(f"  LLM URL: {parsed.llm_url}")
        return 0
    
    # Create config
    config = ChainConfig(
        llm_base_url=parsed.llm_url,
        default_model=parsed.model,
    )
    
    # Build chain
    chain = AgentChain(config) \
        .requirements(parsed.requirements) \
        .model(parsed.model) \
        .output(parsed.output)
    
    # Configure agent-specific models
    if parsed.planner_model:
        chain.configure("planner", model=parsed.planner_model)
    if parsed.coder_model:
        chain.configure("coder", model=parsed.coder_model)
    
    # Add event handlers
    chain.on(Event.CHAIN_START, lambda e, d: print_event(e, d, parsed.verbose))
    chain.on(Event.CHAIN_COMPLETE, lambda e, d: print_event(e, d, parsed.verbose))
    chain.on(Event.AGENT_START, lambda e, d: print_event(e, d, parsed.verbose))
    chain.on(Event.AGENT_COMPLETE, lambda e, d: print_event(e, d, parsed.verbose))
    chain.on(Event.TASK_START, lambda e, d: print_event(e, d, parsed.verbose))
    chain.on(Event.TASK_COMPLETE, lambda e, d: print_event(e, d, parsed.verbose))
    chain.on(Event.TASK_FAILED, lambda e, d: print_event(e, d, parsed.verbose))
    chain.on(Event.AGENT_ERROR, lambda e, d: print_event(e, d, parsed.verbose))
    chain.on(Event.PROGRESS, lambda e, d: print_event(e, d, parsed.verbose))
    
    # Run
    try:
        result = chain.run()
        
        if result.success:
            print(f"Output written to: {os.path.abspath(parsed.output)}")
            return 0
        else:
            print(f"Error: {result.error}", file=sys.stderr)
            return 1
    
    except KeyboardInterrupt:
        print("\n\nInterrupted by user")
        return 130
    
    except Exception as e:
        print(f"Fatal error: {e}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    sys.exit(main())
