"""
Real-time CloudWatch log monitoring for Lambda functions
"""
import click
import json
import time
from datetime import datetime, timedelta
from typing import Optional, List, Dict
from botocore.exceptions import ClientError
from ai_lls_lib.cli.aws_client import AWSClient

try:
    from rich.console import Console
    from rich.syntax import Syntax
    from rich.table import Table
    from rich.live import Live
    from rich.panel import Panel
    from rich.text import Text
    from rich import box
    HAS_RICH = True
except ImportError:
    HAS_RICH = False
    Console = None


def get_log_groups(aws_client: AWSClient, environment: str) -> List[str]:
    """Get relevant CloudWatch log groups for the environment"""
    # Map environment to stack name pattern
    stack_prefix = "landline-api-staging" if environment == "staging" else "landline-api"

    # Key Lambda functions to monitor
    lambda_functions = [
        "PhoneVerifyHandler",
        "BulkUploadHandler",
        "BulkProcessHandler",
        "PlansHandler",
        "PaymentHandler",
        "UserProfileHandler"
    ]

    log_groups = []
    for func in lambda_functions:
        log_group = f"/aws/lambda/{stack_prefix}-{func}"
        log_groups.append(log_group)

    return log_groups


def format_log_event(event: Dict, use_rich: bool = True) -> str:
    """Format a CloudWatch log event for display"""
    timestamp = datetime.fromtimestamp(event.get('timestamp', 0) / 1000)
    message = event.get('message', '')

    # Try to parse JSON message
    try:
        if message.strip().startswith('{'):
            parsed = json.loads(message)

            # Check for external API calls
            if 'external_api_call' in message.lower() or 'landlineremover.com' in message:
                if use_rich and HAS_RICH:
                    return f"[bold green]{timestamp.strftime('%H:%M:%S')}[/bold green] [cyan]EXTERNAL API:[/cyan] {message}"
                else:
                    return f"{timestamp.strftime('%H:%M:%S')} EXTERNAL API: {message}"

            # Check for cache events
            if 'cache' in message.lower():
                if use_rich and HAS_RICH:
                    return f"[bold blue]{timestamp.strftime('%H:%M:%S')}[/bold blue] [yellow]CACHE:[/yellow] {message}"
                else:
                    return f"{timestamp.strftime('%H:%M:%S')} CACHE: {message}"

            # Check for errors
            if 'error' in message.lower() or 'exception' in message.lower():
                if use_rich and HAS_RICH:
                    return f"[bold red]{timestamp.strftime('%H:%M:%S')}[/bold red] [red]ERROR:[/red] {message}"
                else:
                    return f"{timestamp.strftime('%H:%M:%S')} ERROR: {message}"

            # Format structured logs
            if use_rich and HAS_RICH:
                message = json.dumps(parsed, indent=2)
    except (json.JSONDecodeError, ValueError):
        pass

    # Default formatting
    if use_rich and HAS_RICH:
        return f"[dim]{timestamp.strftime('%H:%M:%S')}[/dim] {message}"
    else:
        return f"{timestamp.strftime('%H:%M:%S')} {message}"


def tail_logs(aws_client: AWSClient, log_groups: List[str], duration: int = 300, follow: bool = True):
    """Tail CloudWatch logs in real-time"""
    console = Console() if HAS_RICH else None

    # Calculate start time
    start_time = int((datetime.utcnow() - timedelta(seconds=duration)).timestamp() * 1000)

    # Track last event time for each log group
    last_event_times = {group: start_time for group in log_groups}

    if console and HAS_RICH:
        console.print(Panel.fit(
            f"[bold cyan]Monitoring {len(log_groups)} Lambda functions[/bold cyan]\n"
            f"[dim]Press Ctrl+C to stop[/dim]",
            title="CloudWatch Log Monitor",
            border_style="cyan"
        ))
        console.print()
    else:
        click.echo(f"Monitoring {len(log_groups)} Lambda functions")
        click.echo("Press Ctrl+C to stop\n")

    try:
        while True:
            events_found = False

            for log_group in log_groups:
                try:
                    # Use filter_log_events for real-time tailing
                    response = aws_client.logs.filter_log_events(
                        logGroupName=log_group,
                        startTime=last_event_times[log_group],
                        limit=100
                    )

                    events = response.get('events', [])

                    if events:
                        events_found = True
                        # Update last event time
                        last_event_times[log_group] = events[-1]['timestamp'] + 1

                        # Display log group header
                        if console and HAS_RICH:
                            console.print(f"\n[bold magenta]═══ {log_group} ═══[/bold magenta]")
                        else:
                            click.echo(f"\n=== {log_group} ===")

                        # Display events
                        for event in events:
                            formatted = format_log_event(event, use_rich=(console is not None))
                            if console and HAS_RICH:
                                console.print(formatted)
                            else:
                                click.echo(formatted)

                except ClientError as e:
                    if e.response['Error']['Code'] != 'ResourceNotFoundException':
                        if console and HAS_RICH:
                            console.print(f"[yellow]Warning: {e}[/yellow]")
                        else:
                            click.echo(f"Warning: {e}", err=True)

            if not follow:
                break

            # Sleep briefly before next poll
            time.sleep(2 if events_found else 5)

    except KeyboardInterrupt:
        if console and HAS_RICH:
            console.print("\n[yellow]Monitoring stopped[/yellow]")
        else:
            click.echo("\nMonitoring stopped")


def start_live_tail(aws_client: AWSClient, log_groups: List[str]):
    """Start a CloudWatch Logs Live Tail session (requires AWS SDK v2)"""
    console = Console() if HAS_RICH else None

    try:
        # Start live tail session
        response = aws_client.logs.start_live_tail(
            logGroupIdentifiers=log_groups,
            logStreamNamePrefixes=[],
            logEventFilterPattern=""
        )

        session_id = response.get('sessionId')
        session_url = response.get('sessionUrl')

        if console and HAS_RICH:
            console.print(Panel.fit(
                f"[bold green]Live Tail session started[/bold green]\n"
                f"Session ID: {session_id}\n"
                f"[dim]Note: Live Tail API requires WebSocket support[/dim]",
                title="CloudWatch Live Tail",
                border_style="green"
            ))
        else:
            click.echo(f"Live Tail session started")
            click.echo(f"Session ID: {session_id}")
            click.echo(f"Note: Live Tail API requires WebSocket support")

        # Note: Full WebSocket implementation would be needed here
        # For now, fall back to filter_log_events polling
        click.echo("\nFalling back to standard log polling...")
        tail_logs(aws_client, log_groups, duration=300, follow=True)

    except ClientError as e:
        if 'start_live_tail' in str(e):
            # Fall back to regular tailing if Live Tail not available
            if console and HAS_RICH:
                console.print("[yellow]Live Tail API not available, using standard polling[/yellow]")
            else:
                click.echo("Live Tail API not available, using standard polling")
            tail_logs(aws_client, log_groups, duration=300, follow=True)
        else:
            raise


@click.group(name="monitor")
def monitor_group():
    """Monitor CloudWatch logs in real-time"""
    pass


@monitor_group.command()
@click.option('--staging', is_flag=True, help='Monitor staging environment (default: production)')
@click.option('--production', is_flag=True, help='Monitor production environment')
@click.option('--duration', default=300, help='How far back to start (seconds, default: 300)')
@click.option('--follow', is_flag=True, default=True, help='Follow logs in real-time (default: true)')
@click.option('--filter', 'filter_pattern', help='CloudWatch filter pattern to apply')
@click.option('--profile', help='AWS profile to use')
@click.option('--region', default='us-east-1', help='AWS region')
def logs(staging, production, duration, follow, filter_pattern, profile, region):
    """Tail CloudWatch logs for Lambda functions

    Examples:
        ai-lls monitor logs --staging
        ai-lls monitor logs --production
        ai-lls monitor logs --staging --filter "ERROR"
        ai-lls monitor logs --duration 600 --follow
    """
    # Determine environment
    if staging and production:
        raise click.ClickException("Cannot specify both --staging and --production")

    environment = "staging" if staging else "production"

    # Show warning if Rich not installed
    if not HAS_RICH:
        click.echo("Warning: Install 'rich' library for better output formatting", err=True)
        click.echo("Run: pip install rich", err=True)
        click.echo()

    # Initialize AWS client
    aws_client = AWSClient(region=region, profile=profile)

    # Get log groups
    log_groups = get_log_groups(aws_client, environment)

    click.echo(f"Monitoring {environment} environment...")
    click.echo(f"Log groups: {', '.join([g.split('/')[-1] for g in log_groups])}")
    click.echo()

    # Start tailing logs
    tail_logs(aws_client, log_groups, duration=duration, follow=follow)


@monitor_group.command()
@click.option('--staging', is_flag=True, help='Monitor staging environment')
@click.option('--production', is_flag=True, help='Monitor production environment')
@click.option('--profile', help='AWS profile to use')
@click.option('--region', default='us-east-1', help='AWS region')
def live(staging, production, profile, region):
    """Start CloudWatch Logs Live Tail session (experimental)

    Uses the CloudWatch Logs Live Tail API for real-time streaming.
    Falls back to standard polling if Live Tail is not available.

    Examples:
        ai-lls monitor live --staging
        ai-lls monitor live --production
    """
    # Determine environment
    if staging and production:
        raise click.ClickException("Cannot specify both --staging and --production")

    environment = "staging" if staging else "production"

    # Initialize AWS client
    aws_client = AWSClient(region=region, profile=profile)

    # Get log groups
    log_groups = get_log_groups(aws_client, environment)

    click.echo(f"Starting Live Tail for {environment} environment...")

    # Start live tail
    start_live_tail(aws_client, log_groups)


# Export the group for registration
__all__ = ['monitor_group']
