import os
import subprocess
import shutil
import urllib.request
import tarfile
import re
from pathlib import Path
from rich.panel import Panel
from rich.prompt import Prompt, Confirm
from rich.progress import Progress
from rich.table import Table
from .utils import console

# using 0.8.1
SERVER_URL = "https://github.com/TES3MP/TES3MP/releases/download/tes3mp-0.8.1/tes3mp-server-GNU+Linux-x86_64-release-0.8.1-68954091c5-6da3fdea59.tar.gz"
SERVER_DIR = Path.home() / "Games" / "TES3MP_Server"
SERVER_PORT = 25565

def get_server_root():
    """Find the server installation folder."""
    if not SERVER_DIR.exists():
        return None
    for pattern in ["TES3MP-Server*", "TES3MP-server*", "tes3mp-server*"]:
        server_root = next(SERVER_DIR.glob(pattern), None)
        if server_root:
            return server_root
    return None

def get_tailscale_ip():
    """Get the user's Tailscale IP address."""
    try:
        result = subprocess.run(["tailscale", "ip", "-4"], capture_output=True, text=True)
        if result.returncode == 0:
            return result.stdout.strip()
    except Exception:
        pass
    return None

def is_tailscale_running():
    """Check if Tailscale daemon is running."""
    try:
        result = subprocess.run(["tailscale", "status"], capture_output=True, text=True)
        return result.returncode == 0
    except Exception:
        return False


def install_tailscale():
    """Offer to install Tailscale if not present."""
    console.print(Panel("[bold blue]Install Tailscale[/bold blue]", expand=False))
    console.print("[yellow]Tailscale provides secure private networking for your server.[/yellow]")
    console.print("[dim]This is optional - you can use public IP instead.[/dim]\n")
    
    if not Confirm.ask("Install Tailscale now?"):
        return False
    
    console.print("[cyan][*] Installing Tailscale...[/cyan]")
    try:
        # Use the official install script
        subprocess.run(
            "curl -fsSL https://tailscale.com/install.sh | sh",
            shell=True, check=True
        )
        console.print("[green][+] Tailscale installed![/green]")
        console.print("[yellow]Run 'sudo tailscale up' to connect.[/yellow]")
        return True
    except subprocess.CalledProcessError as e:
        console.print(f"[red][!] Installation failed: {e}[/red]")
        console.print("[dim]Try manually: curl -fsSL https://tailscale.com/install.sh | sh[/dim]")
        return False


def start_tailscale():
    """Start Tailscale if it's not running."""
    if is_tailscale_running():
        return True
    
    # Check if Tailscale is even installed
    if not shutil.which("tailscale"):
        console.print("[yellow][*] Tailscale is not installed.[/yellow]")
        if Confirm.ask("Install Tailscale now?"):
            install_tailscale()
        return False
        
    console.print("[yellow][*] Tailscale is not running.[/yellow]")
    
    if Confirm.ask("Start Tailscale now?"):
        try:
            # Try systemd first
            console.print("[cyan][*] Starting Tailscale...[/cyan]")
            result = subprocess.run(["systemctl", "is-system-running"], capture_output=True, text=True)
            
            if result.returncode == 0 or "running" in result.stdout:
                # Systemd is available
                subprocess.run(["sudo", "systemctl", "start", "tailscaled"], check=True)
                subprocess.run(["sudo", "tailscale", "up"], check=True)
                console.print("[green][+] Tailscale started![/green]")
                return True
            else:
                # Non-systemd environment (like Cloud Shell)
                console.print("[yellow][*] Systemd not available. Trying direct start...[/yellow]")
                subprocess.run(["sudo", "tailscaled", "&"], shell=True)
                import time
                time.sleep(2)
                subprocess.run(["sudo", "tailscale", "up"])
                return True
                
        except subprocess.CalledProcessError as e:
            console.print(f"[red][!] Failed to start Tailscale: {e}[/red]")
            console.print("[dim]For non-systemd systems, try: sudo tailscaled & sudo tailscale up[/dim]")
            return False
    return False


def check_server_dependencies():
    """Check and install required dependencies for the server."""
    import shutil
    
    missing = []
    
    # Check for libluajit
    try:
        result = subprocess.run(["ldconfig", "-p"], capture_output=True, text=True)
        if "libluajit" not in result.stdout:
            missing.append("libluajit")
    except Exception:
        pass
    
    if not missing:
        return True
    
    console.print(f"[yellow][*] Missing server dependencies: {', '.join(missing)}[/yellow]")
    
    if Confirm.ask("Install missing dependencies now?"):
        try:
            # Detect package manager and install
            if shutil.which("apt-get"):
                console.print("[cyan][*] Installing with apt...[/cyan]")
                subprocess.run(["sudo", "apt-get", "update"], check=False)
                subprocess.run(["sudo", "apt-get", "install", "-y", "libluajit-5.1-2"], check=True)
            elif shutil.which("yum"):
                console.print("[cyan][*] Installing with yum...[/cyan]")
                subprocess.run(["sudo", "yum", "install", "-y", "luajit"], check=True)
            elif shutil.which("dnf"):
                console.print("[cyan][*] Installing with dnf...[/cyan]")
                subprocess.run(["sudo", "dnf", "install", "-y", "luajit"], check=True)
            elif shutil.which("pacman"):
                console.print("[cyan][*] Installing with pacman...[/cyan]")
                subprocess.run(["sudo", "pacman", "-S", "--noconfirm", "luajit"], check=True)
            elif shutil.which("apk"):
                console.print("[cyan][*] Installing with apk...[/cyan]")
                subprocess.run(["sudo", "apk", "add", "luajit"], check=True)
            else:
                console.print("[red][!] Unknown package manager. Please install libluajit manually.[/red]")
                return False
            
            console.print("[green][+] Dependencies installed![/green]")
            return True
        except subprocess.CalledProcessError as e:
            console.print(f"[red][!] Installation failed: {e}[/red]")
            return False
    
    return False


def install_server():
    """Download and extract the server binaries."""
    if SERVER_DIR.exists():
        console.print(f"[yellow][*] Server already installed at {SERVER_DIR}[/yellow]")
        return get_server_root()
        
    if not Confirm.ask(f"Install server to {SERVER_DIR}?"):
        return None
    
    # Check dependencies first
    check_server_dependencies()
        
    SERVER_DIR.mkdir(parents=True, exist_ok=True)
    tar_path = SERVER_DIR / "server.tar.gz"
    
    console.print("[cyan][*] Downloading Server binaries...[/cyan]")
    
    with Progress() as progress:
        task = progress.add_task("Downloading...", total=None)
        try:
            urllib.request.urlretrieve(SERVER_URL, tar_path)
            progress.update(task, completed=100, total=100)
        except Exception as e:
            console.print(f"[bold red][!] Download failed: {e}[/bold red]")
            return None
    
    console.print("[*] Extracting...")
    with tarfile.open(tar_path) as tar:
        tar.extractall(path=SERVER_DIR)
    os.remove(tar_path)
    
    console.print("[green][+] Server installed![/green]")
    return get_server_root()

def configure_server(server_root):
    """Configure server name and password."""
    cfg_path = server_root / "tes3mp-server-default.cfg"
    if not cfg_path.exists():
        console.print("[bold red][!] Config file missing.[/bold red]")
        return False

    name = Prompt.ask("Enter Server Name", default="My TES3MP Server")
    password = Prompt.ask("Enter Password (leave empty for public)", default="")

    with open(cfg_path, 'r') as f:
        cfg = f.read()

    cfg = re.sub(r'hostname = ".*?"', f'hostname = "{name}"', cfg)
    cfg = re.sub(r'password = ".*?"', f'password = "{password}"', cfg)

    with open(cfg_path, 'w') as f:
        f.write(cfg)
        
    console.print(f"[green][+] Server configured: {name}[/green]")
    return True

def show_connection_info():
    """Display connection information for friends."""
    # Try to start Tailscale if not running
    if not is_tailscale_running():
        start_tailscale()
    
    ts_ip = get_tailscale_ip()
    
    console.print(Panel("[bold cyan]How to Connect[/bold cyan]", expand=False))
    
    table = Table(show_header=False, box=None)
    table.add_column("Label", style="bold")
    table.add_column("Value", style="green")
    
    if ts_ip:
        table.add_row("Tailscale IP:", ts_ip)
        table.add_row("Port:", str(SERVER_PORT))
        table.add_row("Full Address:", f"{ts_ip}:{SERVER_PORT}")
    else:
        table.add_row("Status:", "[red]Tailscale not running[/red]")
        
    console.print(table)
    console.print()
    
    if ts_ip:
        console.print("[bold]Share this with your friends:[/bold]")
        console.print(f"  [cyan]{ts_ip}:{SERVER_PORT}[/cyan]")
        console.print()
        console.print("[dim]Friends need:[/dim]")
        console.print("  1. TES3MP installed (pip install tes3mp-easy)")
        console.print("  2. Tailscale connected to your network")
        console.print("  3. Same Morrowind game files as you")

def start_server(server_root):
    """Start the server process."""
    server_bin = server_root / "tes3mp-server"
    
    if not server_bin.exists():
        console.print("[bold red][!] Server binary not found.[/bold red]")
        return
    
    # Show connection info first
    show_connection_info()
    
    console.print()
    console.print("[bold green]Starting server...[/bold green]")
    console.print("[dim]Press Ctrl+C to stop the server[/dim]")
    console.print()
    
    try:
        # Run server in foreground
        subprocess.run([str(server_bin)], cwd=str(server_root))
    except KeyboardInterrupt:
        console.print("\n[yellow]Server stopped.[/yellow]")


def configure_server_data():
    """Configure the path to ESM files for the server."""
    from .utils import save_data_path, load_stored_data_path
    
    console.print(Panel("[bold blue]Configure ESM Files[/bold blue]", expand=False))
    console.print("[yellow]The server needs the ESM files to set checksum requirements.[/yellow]")
    console.print("[dim]Only the .esm files are required (~95MB), not the full game.[/dim]\n")
    
    current_path = load_stored_data_path()
    if current_path and current_path.exists():
        console.print(f"Current path: [cyan]{current_path}[/cyan]")
        if not Confirm.ask("Do you want to change it?"):
            return current_path
    
    console.print("\nEnter the path to folder containing Morrowind.esm, Tribunal.esm, Bloodmoon.esm")
    
    while True:
        path_str = Prompt.ask("ESM Files Path")
        data_path = Path(path_str).expanduser().resolve()
        
        if (data_path / "Morrowind.esm").exists():
            save_data_path(data_path)
            console.print(f"[green]✅ ESM path saved: {data_path}[/green]")
            
            # Check which ESM files are present
            for esm in ["Morrowind.esm", "Tribunal.esm", "Bloodmoon.esm"]:
                if (data_path / esm).exists():
                    console.print(f"  [green]✓[/green] {esm}")
                else:
                    console.print(f"  [red]✗[/red] {esm} [dim](optional)[/dim]")
            
            return data_path
        else:
            console.print("[bold red][!] Morrowind.esm not found in that folder.[/bold red]")
            if not Confirm.ask("Try again?"):
                return None


def get_public_ip():
    """Get the server's public IP address."""
    try:
        import urllib.request
        return urllib.request.urlopen('https://api.ipify.org', timeout=5).read().decode('utf8')
    except Exception:
        return None


def setup_server():
    """Main server menu."""
    console.print(Panel("[bold blue]Host a Server[/bold blue]", expand=False))
    
    # Ensure server is installed
    server_root = get_server_root()
    if not server_root:
        server_root = install_server()
        if not server_root:
            return
    
    while True:
        console.print()
        console.print("[bold]Server Menu:[/bold]")
        console.print("1. [green]Start Server[/green]")
        console.print("2. Show Connection Info")
        console.print("3. Configure (Name/Password)")
        console.print("4. [cyan]Setup ESM Files[/cyan]")
        console.print("5. Back to Main Menu")
        
        choice = Prompt.ask("Select", choices=["1", "2", "3", "4", "5"])
        
        if choice == "1":
            start_server(server_root)
        elif choice == "2":
            show_connection_info()
            # Also show public IP
            public_ip = get_public_ip()
            if public_ip:
                console.print(f"\n[bold]Public IP:[/bold] [green]{public_ip}:{SERVER_PORT}[/green]")
                console.print("[dim]Use this if hosting on a VPS/cloud server[/dim]")
            Prompt.ask("\nPress Enter to continue")
        elif choice == "3":
            configure_server(server_root)
            Prompt.ask("\nPress Enter to continue")
        elif choice == "4":
            configure_server_data()
            Prompt.ask("\nPress Enter to continue")
        elif choice == "5":
            break

