#!/usr/bin/env python3
"""
Stargate Server Status Dashboard
A beautiful TUI dashboard for monitoring server status.

Usage:
    status          # One-time snapshot
    status -l       # Live mode (updates every 2s)
    status -l -r 5  # Live mode with 5s refresh
"""

import subprocess
import argparse
import sys
import signal
from datetime import datetime

from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.layout import Layout
from rich.live import Live
from rich.text import Text
from rich.align import Align
from rich import box

console = Console()

# ASCII art header
HEADER = """
 ╔═╗╔╦╗╔═╗╦═╗╔═╗╔═╗╔╦╗╔═╗
 ╚═╗ ║ ╠═╣╠╦╝║ ╦╠═╣ ║ ║╣
 ╚═╝ ╩ ╩ ╩╩╚═╚═╝╩ ╩ ╩ ╚═╝
"""

def ssh_command(cmd: str, timeout: int = 5) -> str:
    """Execute command on server via SSH."""
    try:
        result = subprocess.run(
            ["ssh", "-o", "ConnectTimeout=5", "server", cmd],
            capture_output=True,
            text=True,
            timeout=timeout
        )
        return result.stdout.strip() if result.returncode == 0 else ""
    except (subprocess.TimeoutExpired, Exception):
        return ""


def fetch_data() -> dict:
    """Fetch all data from server."""
    return {
        "uptime": ssh_command("uptime -p"),
        "load": ssh_command("cat /proc/loadavg | cut -d' ' -f1-3"),
        "memory": ssh_command("free -h | awk '/^Mem:/ {print $3\"/\"$2}'"),
        "onion_main": ssh_command("sudo cat /var/lib/tor/krisyotam/hostname"),
        "onion_notes": ssh_command("sudo cat /var/lib/tor/notes-krisyotam/hostname"),
        "nginx": ssh_command("systemctl is-active nginx"),
        "tor": ssh_command("systemctl is-active tor"),
        "disks": ssh_command("df -h / /home /mnt/storage 2>/dev/null | tail -n +2"),
        "services": ssh_command("docker service ls --format '{{.Name}}|{{.Replicas}}'"),
        "containers": ssh_command("docker ps --format '{{.Names}}|{{.Status}}' | head -12"),
    }


def make_header() -> Panel:
    """Create header panel."""
    header_text = Text(HEADER, style="bold magenta", justify="center")
    return Panel(
        Align.center(header_text),
        box=box.ROUNDED,
        border_style="magenta",
        padding=(0, 0),
    )


def make_onion_panel(data: dict) -> Panel:
    """Create Tor hidden services panel."""
    table = Table(show_header=False, box=None, padding=(0, 2))
    table.add_column("Site", style="bold white", width=22)
    table.add_column("Onion Address", style="green")

    onion_main = data.get("onion_main") or "[dim]unavailable[/dim]"
    onion_notes = data.get("onion_notes") or "[dim]unavailable[/dim]"

    table.add_row("krisyotam.com", onion_main)
    table.add_row("notes.krisyotam.com", onion_notes)

    return Panel(
        table,
        title="[bold cyan]TOR HIDDEN SERVICES[/bold cyan]",
        box=box.ROUNDED,
        border_style="cyan",
    )


def make_system_panel(data: dict) -> Panel:
    """Create system info panel."""
    table = Table(show_header=False, box=None, padding=(0, 2))
    table.add_column("Metric", style="bold white", width=15)
    table.add_column("Value", style="white")

    table.add_row("Uptime", data.get("uptime") or "unavailable")
    table.add_row("Load", data.get("load") or "unavailable")
    table.add_row("Memory", data.get("memory") or "unavailable")

    nginx_status = data.get("nginx", "")
    tor_status = data.get("tor", "")

    nginx_style = "[green]running[/green]" if nginx_status == "active" else "[red]stopped[/red]"
    tor_style = "[green]running[/green]" if tor_status == "active" else "[red]stopped[/red]"

    table.add_row("nginx", nginx_style)
    table.add_row("tor", tor_style)

    return Panel(
        table,
        title="[bold cyan]SYSTEM[/bold cyan]",
        box=box.ROUNDED,
        border_style="cyan",
    )


def make_disk_panel(data: dict) -> Panel:
    """Create disk usage panel."""
    table = Table(box=box.SIMPLE, padding=(0, 1))
    table.add_column("Mount", style="bold white", width=16)
    table.add_column("Size", justify="right", width=8)
    table.add_column("Used", justify="right", width=8)
    table.add_column("Avail", justify="right", width=8)
    table.add_column("Use%", justify="right", width=8)

    disks = data.get("disks", "")
    if disks:
        for line in disks.strip().split("\n"):
            if line:
                parts = line.split()
                if len(parts) >= 5:
                    fs = parts[0][:16]
                    size, used, avail = parts[1], parts[2], parts[3]
                    pct = parts[4].rstrip('%')

                    try:
                        pct_int = int(pct)
                        if pct_int >= 90:
                            pct_style = f"[red]{pct}%[/red]"
                        elif pct_int >= 70:
                            pct_style = f"[yellow]{pct}%[/yellow]"
                        else:
                            pct_style = f"[green]{pct}%[/green]"
                    except ValueError:
                        pct_style = f"{pct}%"

                    table.add_row(fs, size, used, avail, pct_style)

    return Panel(
        table,
        title="[bold cyan]DISK USAGE[/bold cyan]",
        box=box.ROUNDED,
        border_style="cyan",
    )


def make_services_panel(data: dict) -> Panel:
    """Create Docker Swarm services panel."""
    table = Table(box=box.SIMPLE, padding=(0, 1))
    table.add_column("Service", style="bold white", width=35)
    table.add_column("Replicas", justify="right", width=12)

    services = data.get("services", "")
    if services:
        for line in services.strip().split("\n"):
            if "|" in line:
                name, replicas = line.split("|", 1)
                if replicas.strip() == "1/1":
                    rep_style = f"[green]{replicas}[/green]"
                else:
                    rep_style = f"[red]{replicas}[/red]"
                table.add_row(name.strip(), rep_style)
    else:
        table.add_row("[dim]No services found[/dim]", "")

    return Panel(
        table,
        title="[bold cyan]DOCKER SWARM[/bold cyan]",
        box=box.ROUNDED,
        border_style="cyan",
    )


def make_containers_panel(data: dict) -> Panel:
    """Create Docker containers panel."""
    table = Table(box=box.SIMPLE, padding=(0, 1))
    table.add_column("Container", style="bold white", width=28)
    table.add_column("Status", width=30)

    containers = data.get("containers", "")
    if containers:
        for line in containers.strip().split("\n"):
            if "|" in line:
                name, status = line.split("|", 1)
                name = name.strip()[:28]
                status = status.strip()[:30]

                if "Up" in status:
                    status_style = f"[green]{status}[/green]"
                else:
                    status_style = f"[red]{status}[/red]"
                table.add_row(name, status_style)
    else:
        table.add_row("[dim]No containers found[/dim]", "")

    return Panel(
        table,
        title="[bold cyan]CONTAINERS[/bold cyan]",
        box=box.ROUNDED,
        border_style="cyan",
    )


def make_footer(live_mode: bool, refresh: int) -> Text:
    """Create footer text."""
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    if live_mode:
        return Text(f" Last updated: {timestamp} │ Refresh: {refresh}s │ Press Ctrl+C to exit ", style="dim")
    else:
        return Text(f" Last updated: {timestamp} │ Run with -l for live mode ", style="dim")


def build_dashboard(data: dict, live_mode: bool = False, refresh: int = 2) -> Layout:
    """Build the complete dashboard layout."""
    layout = Layout()

    layout.split_column(
        Layout(name="header", size=6),
        Layout(name="onion", size=6),
        Layout(name="middle", size=9),
        Layout(name="bottom"),
        Layout(name="footer", size=1),
    )

    layout["middle"].split_row(
        Layout(name="system"),
        Layout(name="disks"),
    )

    layout["bottom"].split_row(
        Layout(name="services"),
        Layout(name="containers"),
    )

    layout["header"].update(make_header())
    layout["onion"].update(make_onion_panel(data))
    layout["system"].update(make_system_panel(data))
    layout["disks"].update(make_disk_panel(data))
    layout["services"].update(make_services_panel(data))
    layout["containers"].update(make_containers_panel(data))
    layout["footer"].update(Align.center(make_footer(live_mode, refresh)))

    return layout


def main():
    parser = argparse.ArgumentParser(description="Stargate Server Status Dashboard")
    parser.add_argument("-l", "--live", action="store_true", help="Enable live updating mode")
    parser.add_argument("-r", "--refresh", type=int, default=2, help="Refresh interval in seconds (default: 2)")
    args = parser.parse_args()

    def signal_handler(sig, frame):
        console.clear()
        sys.exit(0)

    signal.signal(signal.SIGINT, signal_handler)

    if args.live:
        with Live(console=console, refresh_per_second=1, screen=True) as live:
            while True:
                data = fetch_data()
                live.update(build_dashboard(data, live_mode=True, refresh=args.refresh))
                import time
                time.sleep(args.refresh)
    else:
        console.clear()
        data = fetch_data()
        console.print(build_dashboard(data))


if __name__ == "__main__":
    main()
