"""Click-based CLI entry point"""

import click
import os
import signal
import subprocess
import sys
import time
from typing import List, Optional

from rich.console import Console
from rich.live import Live
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

from vallignus.proxy import VallignusProxy
from vallignus.logger import FlightLogger
from vallignus.rules import RulesEngine


console = Console()
_subprocess: Optional[subprocess.Popen] = None


def parse_domains(domains_str: str) -> set:
    """Parse comma-separated domains string into a set"""
    domains = [d.strip().lower() for d in domains_str.split(',') if d.strip()]
    return set(domains)


def create_status_table(proxy: VallignusProxy, rules: RulesEngine) -> Table:
    """Create a rich table showing proxy status"""
    table = Table(show_header=True, header_style="bold magenta")
    table.add_column("Metric", style="cyan")
    table.add_column("Value", style="green")
    
    spend, budget, remaining = rules.get_budget_status()
    
    table.add_row("Status", "🟢 Running" if proxy.is_running else "🔴 Stopped")
    table.add_row("Allowed Requests", str(proxy.allowed_count))
    table.add_row("Blocked Requests", str(proxy.blocked_count))
    
    if budget is not None:
        table.add_row("Budget", f"${budget:.2f}")
        table.add_row("Spent", f"${spend:.4f}")
        table.add_row("Remaining", f"${remaining:.2f}" if remaining is not None else "N/A")
        
        if remaining is not None:
            percent_used = (spend / budget) * 100 if budget > 0 else 0
            if percent_used >= 100:
                status_text = Text("⚠️  EXCEEDED", style="bold red")
            elif percent_used >= 80:
                status_text = Text(f"⚠️  {percent_used:.1f}%", style="bold yellow")
            else:
                status_text = Text(f"✓ {percent_used:.1f}%", style="green")
            table.add_row("Budget Usage", status_text)
    else:
        table.add_row("Budget", "Unlimited")
        table.add_row("Spent", f"${spend:.4f}")
    
    return table


@click.group()
def cli():
    """Vallignus - Infrastructure-grade firewall for AI agents"""
    pass


@cli.command()
@click.option(
    '--budget',
    type=float,
    default=None,
    help='Budget limit in dollars (e.g., 5.00)'
)
@click.option(
    '--allow',
    required=True,
    help='Comma-separated list of allowed domains (e.g., "github.com,openai.com")'
)
@click.option(
    '--port',
    type=int,
    default=8080,
    help='Proxy port (default: 8080)'
)
@click.option(
    '--log',
    type=str,
    default='flight_log.json',
    help='Path to flight log JSON file (default: flight_log.json)'
)
@click.argument('command', nargs=-1, required=True)
def run(budget: Optional[float], allow: str, port: int, log: str, command: List[str]):
    """
    Run a command through the Vallignus firewall proxy.
    
    Example: vallignus run --budget 5.00 --allow "github.com,openai.com" -- python agent.py
    """
    global _subprocess
    
    if not command:
        console.print("[red]Error: Command is required[/red]")
        sys.exit(1)
    
    # Parse allowed domains
    allowed_domains = parse_domains(allow)
    
    if not allowed_domains:
        console.print("[red]Error: At least one domain must be allowed[/red]")
        sys.exit(1)
    
    # Initialize components
    logger = FlightLogger(log_file=log)
    rules = RulesEngine(allowed_domains, budget)
    proxy = VallignusProxy(allowed_domains, budget, logger, rules)
    
    # Start proxy
    try:
        actual_port = proxy.start(port)
        console.print(f"[green]✓[/green] Proxy started on port {actual_port}")
    except Exception as e:
        console.print(f"[red]Error starting proxy: {e}[/red]")
        sys.exit(1)
    
    # Set up environment for subprocess
    env = os.environ.copy()
    env['HTTP_PROXY'] = f'http://127.0.0.1:{actual_port}'
    env['HTTPS_PROXY'] = f'http://127.0.0.1:{actual_port}'
    env['http_proxy'] = f'http://127.0.0.1:{actual_port}'
    env['https_proxy'] = f'http://127.0.0.1:{actual_port}'
    # Disable SSL verification warnings for mitmproxy
    env['PYTHONWARNINGS'] = 'ignore'
    
    # Start the command
    console.print(f"[cyan]Starting: {' '.join(command)}[/cyan]")
    try:
        _subprocess = subprocess.Popen(
            list(command),
            env=env
        )
    except Exception as e:
        console.print(f"[red]Error starting command: {e}[/red]")
        proxy.stop()
        sys.exit(1)
    
    # Monitor and display status
    def signal_handler(sig, frame):
        """Handle Ctrl+C"""
        console.print("\n[yellow]Shutting down...[/yellow]")
        if _subprocess:
            _subprocess.terminate()
            try:
                _subprocess.wait(timeout=5)
            except subprocess.TimeoutExpired:
                _subprocess.kill()
        proxy.stop()
        sys.exit(0)
    
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)
    
    # Status monitoring loop
    try:
        with Live(console=console, refresh_per_second=2) as live:
            while _subprocess.poll() is None:
                if proxy._should_terminate and not _subprocess.poll():
                    console.print("\n[red]⚠️  Budget exceeded! Terminating process...[/red]")
                    _subprocess.terminate()
                    try:
                        _subprocess.wait(timeout=5)
                    except subprocess.TimeoutExpired:
                        _subprocess.kill()
                    break
                
                status_table = create_status_table(proxy, rules)
                panel = Panel(status_table, title="Vallignus Firewall", border_style="blue")
                live.update(panel)
                time.sleep(0.5)
        
        # Final status
        status_table = create_status_table(proxy, rules)
        panel = Panel(status_table, title="Vallignus Firewall (Final)", border_style="blue")
        console.print(panel)
        
        return_code = _subprocess.returncode
        if return_code != 0:
            console.print(f"\n[yellow]Process exited with code {return_code}[/yellow]")
        
        console.print(f"\n[cyan]Flight log saved to: {log}[/cyan]")
        
    finally:
        proxy.stop()
        if _subprocess and _subprocess.poll() is None:
            _subprocess.terminate()


def main():
    """Entry point for the CLI"""
    cli()


if __name__ == '__main__':
    main()
