from rich.console import Console
from rich.table import Table
from rich.prompt import Prompt, Confirm, IntPrompt
from rich.panel import Panel
import importlib.metadata

# Import Custom Logic
from xenfra.engine import InfraEngine

console = Console()

# --- CONSTANTS ---
SIZES = {
    "1": ("s-1vcpu-1gb", "$6/mo", "1GB RAM / 1 CPU"),
    "2": ("s-1vcpu-2gb", "$12/mo", "2GB RAM / 1 CPU"),
    "3": ("s-2vcpu-4gb", "$24/mo", "4GB RAM / 2 CPU"),
}

IMAGES = {
    "1": ("ubuntu-24-04-x64", "Ubuntu 24.04 LTS"),
    "2": ("debian-12-x64", "Debian 12"),
    "3": ("fedora-39-x64", "Fedora 39"),
}

def print_header(email):
    try:
        # Get the version of the installed 'xenfra' package
        version = importlib.metadata.version("xenfra")
    except importlib.metadata.PackageNotFoundError:
        version = "dev" # Fallback for local development

    console.clear()
    grid = Table.grid(expand=True)
    grid.add_column(justify="center", ratio=1)
    grid.add_row(f"[bold cyan]🧘 XENFRA[/bold cyan] [dim]v{version}[/dim]")
    grid.add_row("[italic]Infrastructure in Zen Mode[/italic]")
    console.print(Panel(
        grid,
        style="cyan",
        subtitle=f"👤 {email} | 📧 support@xenfracloud.com"
    ))

def deploy_menu(engine: InfraEngine):
    console.print("\n[bold green]🛠️  CONFIGURE YOUR SERVER[/bold green]")

    # 1. Name
    name = Prompt.ask("   🏷️  Server Name", default="xenfra-node-01")

    # 2. Image Selection
    console.print("\n   [bold]Select Operating System:[/bold]")
    for k, v in IMAGES.items():
        console.print(f"   [cyan]{k}[/cyan]. {v[1]}")
    img_choice = Prompt.ask("   Choice", choices=list(IMAGES.keys()), default="1")
    selected_image = IMAGES[img_choice][0]

    # 3. Size Selection
    console.print("\n   [bold]Select Power Size:[/bold]")
    for k, v in SIZES.items():
        console.print(f"   [cyan]{k}[/cyan]. {v[2]} ({v[1]})")
    size_choice = Prompt.ask("   Choice", choices=list(SIZES.keys()), default="1")
    selected_size = SIZES[size_choice][0]

    # 4. Final Confirm
    if not Confirm.ask(f"\n🚀 Deploy [cyan]{name}[/cyan]?"):
        return

    # 5. EXECUTE (Delegate to Engine)
    try:
        # This is now a single, blocking call to the stateful engine.
        # The engine handles all the complexity. The CLI just shows the final result.
        result = engine.deploy_server(
            name=name,
            region="blr1", # region can be prompted for in the future
            size=selected_size,
            image=selected_image,
            logger=console.log
        )
        console.print(Panel(
            f"[bold green]✅ SERVER ONLINE & DEPLOYED![/bold green]\n\n"
            f"🌍 IP Address: [bold cyan]{result['ip']}[/bold cyan]\n"
            f"📂 App Path:   [yellow]/root/app[/yellow]\n"
            f"🔑 Login:      ssh root@{result['ip']}",
            title="Deployment Success",
            border_style="green"
        ))
    except Exception as e:
        console.print(Panel(
            f"[bold red]⚠️  DEPLOYMENT FAILED[/bold red]\n\n"
            f"The engine reported a critical error: {e}\n"
            f"Check logs if available on the server.",
            title="Fatal Error",
            border_style="red"
        ))

    Prompt.ask("\nPress Enter to return to menu")

def list_menu(engine: InfraEngine):
    console.print("\n[bold]📡 SCANNING FLEET...[/bold]")
    with console.status("Calling DigitalOcean API..."):
        servers = engine.list_servers()
    
    if not servers:
        console.print("[yellow]   No active servers found.[/yellow]")
    else:
        table = Table(show_header=True, header_style="bold magenta")
        table.add_column("ID", style="dim", width=12)
        table.add_column("Name", style="cyan")
        table.add_column("IP Address", style="green")
        table.add_column("Status")
        table.add_column("Cost", justify="right")
        for s in servers:
            table.add_row(str(s.id), s.name, s.ip_address, s.status, f"${s.size['price_monthly']}/mo")
        console.print(table)
    Prompt.ask("\nPress Enter to return to menu")

def destroy_menu(engine: InfraEngine):
    console.print("\n[bold red]🧨 DESTROY SERVER[/bold red]")
    with console.status("Calling DigitalOcean API..."):
        servers = engine.list_servers()

    if not servers:
        console.print("[yellow]   No servers to destroy.[/yellow]")
        Prompt.ask("\nPress Enter to return")
        return

    for i, s in enumerate(servers):
        console.print(f"   [{i+1}] {s.name} ({s.ip_address})")

    choice = IntPrompt.ask("\n   Select Server to Destroy (0 to cancel)", choices=[str(i) for i in range(len(servers) + 1)], show_choices=False)
    if choice == 0:
        return

    target = servers[choice-1]

    if Confirm.ask(f"   Are you SURE you want to delete [red]{target.name}[/red]?"):
        with console.status(f"💥 Destroying {target.name}..."):
            engine.destroy_server(target.id)
        console.print(f"[green]   Server {target.name} destroyed.[/green]")
    
    Prompt.ask("\nPress Enter to return")


def main():
    try:
        engine = InfraEngine()
        user = engine.get_user_info()
        while True:
            print_header(user['email'])
            console.print("\n[bold]MAIN MENU:[/bold]")
            console.print("   [1] 🚀 Deploy New Server")
            console.print("   [2] 📋 List Active Servers")
            console.print("   [3] 🧨 Destroy a Server")
            console.print("   [4] 🚪 Exit")
            choice = Prompt.ask("\n   👉 Select Option", choices=["1", "2", "3", "4"], default="2")

            if choice == "1":
                deploy_menu(engine)
            elif choice == "2":
                list_menu(engine)
            elif choice == "3":
                destroy_menu(engine)
            elif choice == "4":
                console.print("[cyan]Goodbye, CEO.[/cyan]")
                break
    except Exception as e:
        console.print(f"[bold red]CRITICAL ERROR:[/bold red] {e}")

if __name__ == "__main__":
    main()
