"""CLI commands for the Event Aggregator service.

WHY: Provides command-line interface for managing the event aggregator service
that captures Socket.IO events and saves them as structured session documents.
"""

import json
import sys
from pathlib import Path
from typing import Optional

from ...services.event_aggregator import (
    get_aggregator,
    start_aggregator,
    stop_aggregator,
    aggregator_status
)
from ...models.agent_session import AgentSession
from ...core.logger import get_logger


logger = get_logger("cli.aggregate")


def aggregate_command(args):
    """Main entry point for aggregate commands.
    
    WHY: Routes subcommands to appropriate handlers for managing the
    event aggregator service.
    """
    subcommand = args.aggregate_subcommand
    
    if subcommand == 'start':
        return start_command(args)
    elif subcommand == 'stop':
        return stop_command(args)
    elif subcommand == 'status':
        return status_command(args)
    elif subcommand == 'sessions':
        return sessions_command(args)
    elif subcommand == 'view':
        return view_command(args)
    elif subcommand == 'export':
        return export_command(args)
    else:
        print(f"Unknown subcommand: {subcommand}", file=sys.stderr)
        return 1


def start_command(args):
    """Start the event aggregator service.
    
    WHY: Starts capturing events from the Socket.IO dashboard server
    for building complete session documents.
    """
    print("Starting Event Aggregator service...")
    
    # Check if Socket.IO server is running
    import socket
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.settimeout(1)
            result = s.connect_ex(('127.0.0.1', 8765))
            if result != 0:
                print("Warning: Socket.IO server not detected on port 8765")
                print("The aggregator requires the dashboard server to be running.")
                print("Start it with: claude-mpm monitor")
                if not args.force:
                    return 1
    except Exception as e:
        logger.error(f"Error checking server status: {e}")
    
    # Start the aggregator
    if start_aggregator():
        print("✅ Event Aggregator started successfully")
        print(f"Capturing events from localhost:8765")
        print(f"Sessions will be saved to: .claude-mpm/sessions/")
        
        # Show initial status
        status = aggregator_status()
        print(f"\nStatus:")
        print(f"  Connected: {status['connected']}")
        print(f"  Active sessions: {status['active_sessions']}")
        
        if args.daemon:
            print("\nAggregator running in background. Use 'claude-mpm aggregate stop' to stop it.")
        else:
            print("\nPress Ctrl+C to stop the aggregator...")
            try:
                # Keep running until interrupted
                import time
                while True:
                    time.sleep(1)
            except KeyboardInterrupt:
                print("\nStopping aggregator...")
                stop_aggregator()
        
        return 0
    else:
        print("❌ Failed to start Event Aggregator")
        print("Check that python-socketio is installed: pip install python-socketio")
        return 1


def stop_command(args):
    """Stop the event aggregator service.
    
    WHY: Gracefully stops the aggregator and saves any active sessions.
    """
    print("Stopping Event Aggregator service...")
    
    # Get status before stopping
    status = aggregator_status()
    active_sessions = status.get('active_sessions', 0)
    
    if active_sessions > 0:
        print(f"Saving {active_sessions} active session(s)...")
    
    stop_aggregator()
    print("✅ Event Aggregator stopped")
    
    # Show final statistics
    if status['total_events'] > 0:
        print(f"\nStatistics:")
        print(f"  Total events captured: {status['total_events']}")
        print(f"  Sessions completed: {status['sessions_completed']}")
        print(f"  Events by type:")
        for event_type, count in sorted(status['events_by_type'].items(), 
                                       key=lambda x: x[1], reverse=True)[:5]:
            print(f"    {event_type}: {count}")
    
    return 0


def status_command(args):
    """Show status of the event aggregator service.
    
    WHY: Provides visibility into what the aggregator is doing and
    what it has captured.
    """
    status = aggregator_status()
    
    print("Event Aggregator Status")
    print("=" * 50)
    print(f"Running: {status['running']}")
    print(f"Connected: {status['connected']}")
    print(f"Server: {status['server']}")
    print(f"Save directory: {status['save_directory']}")
    print()
    print(f"Active sessions: {status['active_sessions']}")
    if status['active_session_ids']:
        for sid in status['active_session_ids']:
            print(f"  - {sid}")
    print()
    print(f"Sessions completed: {status['sessions_completed']}")
    print(f"Total events captured: {status['total_events']}")
    
    if status['events_by_type']:
        print("\nTop event types:")
        for event_type, count in sorted(status['events_by_type'].items(), 
                                       key=lambda x: x[1], reverse=True)[:10]:
            print(f"  {event_type:30s} {count:6d}")
    
    return 0


def sessions_command(args):
    """List captured sessions.
    
    WHY: Shows what sessions have been captured for analysis.
    """
    aggregator = get_aggregator()
    sessions = aggregator.list_sessions(limit=args.limit)
    
    if not sessions:
        print("No sessions found")
        return 0
    
    print(f"Recent Sessions (showing {len(sessions)} of {args.limit} max)")
    print("=" * 80)
    
    for session in sessions:
        print(f"\n📁 {session['file']}")
        print(f"   Session ID: {session['session_id']}")
        print(f"   Start: {session['start_time']}")
        print(f"   End: {session['end_time']}")
        print(f"   Events: {session['events']}")
        print(f"   Delegations: {session['delegations']}")
        print(f"   Prompt: {session['initial_prompt']}")
    
    print(f"\nUse 'claude-mpm aggregate view <session_id>' to view details")
    
    return 0


def view_command(args):
    """View details of a specific session.
    
    WHY: Allows detailed inspection of what happened during a session.
    """
    aggregator = get_aggregator()
    
    # Load the session
    session = aggregator.load_session(args.session_id)
    
    if not session:
        print(f"Session not found: {args.session_id}")
        print("Use 'claude-mpm aggregate sessions' to list available sessions")
        return 1
    
    print(f"Session: {session.session_id}")
    print("=" * 80)
    print(f"Start: {session.start_time}")
    print(f"End: {session.end_time or 'In progress'}")
    print(f"Working directory: {session.working_directory}")
    print(f"Launch method: {session.launch_method}")
    
    if session.git_branch:
        print(f"Git branch: {session.git_branch}")
    
    print(f"\nInitial prompt:")
    print("-" * 40)
    if session.initial_prompt:
        print(session.initial_prompt[:500])
        if len(session.initial_prompt) > 500:
            print("...")
    else:
        print("(No prompt captured)")
    
    print(f"\nMetrics:")
    print("-" * 40)
    metrics = session.metrics
    print(f"Total events: {metrics.total_events}")
    print(f"Delegations: {metrics.total_delegations}")
    print(f"Tool calls: {metrics.total_tool_calls}")
    print(f"File operations: {metrics.total_file_operations}")
    
    if metrics.session_duration_ms:
        duration_sec = metrics.session_duration_ms / 1000
        print(f"Duration: {duration_sec:.1f} seconds")
    
    if metrics.agents_used:
        print(f"\nAgents used: {', '.join(sorted(metrics.agents_used))}")
    
    if metrics.tools_used:
        print(f"\nTools used: {', '.join(sorted(metrics.tools_used))}")
    
    if metrics.files_modified:
        print(f"\nFiles modified ({len(metrics.files_modified)}):")
        for filepath in sorted(metrics.files_modified)[:10]:
            print(f"  - {filepath}")
        if len(metrics.files_modified) > 10:
            print(f"  ... and {len(metrics.files_modified) - 10} more")
    
    if session.delegations:
        print(f"\nDelegations ({len(session.delegations)}):")
        print("-" * 40)
        for i, delegation in enumerate(session.delegations, 1):
            print(f"\n{i}. {delegation.agent_type}")
            print(f"   Task: {delegation.task_description[:100]}")
            if delegation.prompt:
                print(f"   Prompt: {delegation.prompt[:100]}...")
            print(f"   Tools: {len(delegation.tool_operations)}")
            print(f"   Files: {len(delegation.file_changes)}")
            if delegation.duration_ms:
                print(f"   Duration: {delegation.duration_ms/1000:.1f}s")
            print(f"   Status: {'✅ Success' if delegation.success else '❌ Failed'}")
            if delegation.error:
                print(f"   Error: {delegation.error}")
    
    if args.show_events:
        print(f"\nEvents ({len(session.events)}):")
        print("-" * 40)
        for event in session.events[:args.event_limit]:
            print(f"{event.timestamp} [{event.category.value:10s}] {event.event_type}")
            if args.verbose:
                print(f"  Agent: {event.agent_context or 'N/A'}")
                if event.correlation_id:
                    print(f"  Correlation: {event.correlation_id}")
    
    if session.final_response and not args.no_response:
        print(f"\nFinal response:")
        print("-" * 40)
        print(session.final_response[:1000])
        if len(session.final_response) > 1000:
            print("...")
    
    return 0


def export_command(args):
    """Export a session to a file.
    
    WHY: Allows sessions to be exported for external analysis or sharing.
    """
    aggregator = get_aggregator()
    
    # Load the session
    session = aggregator.load_session(args.session_id)
    
    if not session:
        print(f"Session not found: {args.session_id}")
        return 1
    
    # Determine output file
    if args.output:
        output_path = Path(args.output)
    else:
        output_path = Path(f"session_{session.session_id[:8]}_export.json")
    
    # Export based on format
    if args.format == 'json':
        # Full JSON export
        with open(output_path, 'w') as f:
            json.dump(session.to_dict(), f, indent=2)
        print(f"✅ Exported session to {output_path}")
        
    elif args.format == 'summary':
        # Summary export
        summary = {
            'session_id': session.session_id,
            'start_time': session.start_time,
            'end_time': session.end_time,
            'working_directory': session.working_directory,
            'initial_prompt': session.initial_prompt,
            'final_response': session.final_response,
            'metrics': session.metrics.to_dict(),
            'delegations_summary': [
                {
                    'agent': d.agent_type,
                    'task': d.task_description,
                    'duration_ms': d.duration_ms,
                    'success': d.success,
                    'tools_used': len(d.tool_operations),
                    'files_changed': len(d.file_changes)
                }
                for d in session.delegations
            ]
        }
        
        with open(output_path, 'w') as f:
            json.dump(summary, f, indent=2)
        print(f"✅ Exported session summary to {output_path}")
    
    elif args.format == 'events':
        # Events-only export
        events_data = [e.to_dict() for e in session.events]
        
        with open(output_path, 'w') as f:
            json.dump(events_data, f, indent=2)
        print(f"✅ Exported {len(events_data)} events to {output_path}")
    
    return 0


def add_aggregate_parser(subparsers):
    """Add the aggregate command parser.
    
    WHY: Integrates the aggregator commands into the main CLI system.
    """
    aggregate_parser = subparsers.add_parser(
        'aggregate',
        help='Manage event aggregator for capturing agent sessions'
    )
    
    aggregate_subparsers = aggregate_parser.add_subparsers(
        dest='aggregate_subcommand',
        help='Aggregator subcommands'
    )
    
    # Start command
    start_parser = aggregate_subparsers.add_parser(
        'start',
        help='Start the event aggregator service'
    )
    start_parser.add_argument(
        '--daemon', '-d',
        action='store_true',
        help='Run in background as daemon'
    )
    start_parser.add_argument(
        '--force', '-f',
        action='store_true',
        help='Start even if Socket.IO server not detected'
    )
    
    # Stop command
    aggregate_subparsers.add_parser(
        'stop',
        help='Stop the event aggregator service'
    )
    
    # Status command
    aggregate_subparsers.add_parser(
        'status',
        help='Show aggregator status and statistics'
    )
    
    # Sessions command
    sessions_parser = aggregate_subparsers.add_parser(
        'sessions',
        help='List captured sessions'
    )
    sessions_parser.add_argument(
        '--limit', '-l',
        type=int,
        default=10,
        help='Maximum number of sessions to show (default: 10)'
    )
    
    # View command
    view_parser = aggregate_subparsers.add_parser(
        'view',
        help='View details of a specific session'
    )
    view_parser.add_argument(
        'session_id',
        help='Session ID or prefix to view'
    )
    view_parser.add_argument(
        '--show-events', '-e',
        action='store_true',
        help='Show event list'
    )
    view_parser.add_argument(
        '--event-limit',
        type=int,
        default=50,
        help='Maximum events to show (default: 50)'
    )
    view_parser.add_argument(
        '--verbose', '-v',
        action='store_true',
        help='Show verbose event details'
    )
    view_parser.add_argument(
        '--no-response',
        action='store_true',
        help='Don\'t show final response'
    )
    
    # Export command
    export_parser = aggregate_subparsers.add_parser(
        'export',
        help='Export a session to file'
    )
    export_parser.add_argument(
        'session_id',
        help='Session ID or prefix to export'
    )
    export_parser.add_argument(
        '--output', '-o',
        help='Output file path'
    )
    export_parser.add_argument(
        '--format', '-f',
        choices=['json', 'summary', 'events'],
        default='json',
        help='Export format (default: json)'
    )
    
    aggregate_parser.set_defaults(func=aggregate_command)