"""CLI for mesh-optimizer boost commands.

Usage:
    mesh-optimizer boost start [--tier gamer|pro] [--dry-run]
    mesh-optimizer boost stop
    mesh-optimizer boost status
"""
from __future__ import annotations

import json
import sys


def cmd_boost(args):
    """Handle boost subcommands."""
    action = getattr(args, "boost_action", None)
    if action is None:
        cmd_boost_status(args)
    elif action == "start":
        cmd_boost_start(args)
    elif action == "stop":
        cmd_boost_stop(args)
    elif action == "status":
        cmd_boost_status(args)
    elif action == "profiles":
        cmd_boost_profiles(args)
    elif action == "detect":
        cmd_boost_detect(args)
    else:
        print(f"Unknown boost action: {action}")
        sys.exit(1)


def cmd_boost_start(args):
    """Start performance boost."""
    from mesh_boost.boost_engine import BoostEngine
    from mesh_boost.optimizer.base import is_admin

    tier = getattr(args, "tier", "gamer") or "gamer"
    dry_run = getattr(args, "dry_run", False)

    if not is_admin():
        print("WARNING: Running without root/admin — some optimizations will be skipped")
        print("  Tip: Run with sudo (Linux) or as Administrator (Windows)\n")

    print(f"Mesh Boost starting (tier={tier})")
    print("\u2500" * 40)

    engine = BoostEngine(tier=tier)
    result = engine.start(dry_run=dry_run)

    if "error" in result:
        print(f"  Error: {result['error']}")
        sys.exit(1)

    for r in result.get("results", []):
        applied = r.get("applied", [])
        failed = r.get("failed", [])
        skipped = r.get("skipped", [])

        for a in applied:
            print(f"  \033[32m+\033[0m {a}")
        for f in failed:
            print(f"  \033[31mx\033[0m {f}")

    total = result.get("applied", 0)
    fails = result.get("failed", 0)
    skips = result.get("skipped", 0)
    print(f"\n  {total} applied, {fails} failed, {skips} skipped")

    if total > 0:
        print("\n  Boost is \033[32mACTIVE\033[0m")
        print("  Run 'mesh-optimizer boost stop' to restore defaults")


def cmd_boost_stop(args):
    """Stop boost and restore original settings."""
    from mesh_boost.boost_engine import BoostEngine

    engine = BoostEngine()
    result = engine.stop()

    if result.get("status") == "not_active":
        print("Boost is not active")
        return

    print("Boost stopped — original settings restored")
    for r in result.get("results", []):
        for a in r.get("applied", []):
            print(f"  \033[33m~\033[0m {a}")


def cmd_boost_status(args):
    """Show current boost status."""
    from mesh_boost.boost_engine import BoostEngine

    engine = BoostEngine()
    status = engine.status()

    active = status.get("active", False)
    active_str = "\033[32mACTIVE\033[0m" if active else "\033[31mINACTIVE\033[0m"
    plat = status.get("platform", "?")

    print(f"Mesh Boost Status")
    print("\u2500" * 40)
    print(f"  Status:     {active_str}")
    print(f"  Tier:       {status.get('tier', '?')}")
    print(f"  Platform:   {plat}")
    print(f"  Root/Admin: {'yes' if status.get('is_admin') else 'no'}")

    if active:
        uptime = status.get("uptime_s", 0)
        hours = int(uptime // 3600)
        mins = int((uptime % 3600) // 60)
        print(f"  Uptime:     {hours}h {mins}m")

    # Power details
    power = status.get("power", {})
    settings = power.get("settings", {})
    if settings:
        print(f"\n  Power:")
        # Windows: timer resolution
        if "timer_resolution_ms" in settings:
            timer = settings["timer_resolution_ms"]
            color = "\033[32m" if timer <= 1.0 else "\033[33m" if timer <= 5.0 else "\033[31m"
            print(f"    Timer resolution: {color}{timer:.2f}ms\033[0m")
        # Windows: power plan
        plan = settings.get("power_plan", {})
        if plan:
            perf = "HIGH" if plan.get("is_high_perf") else "standard"
            print(f"    Power plan: {perf}")
        # Windows: MMCSS
        mmcss = settings.get("mmcss_system_responsiveness")
        if mmcss is not None:
            print(f"    MMCSS reserved: {mmcss}%")
        # Linux: CPU governor
        gov = settings.get("cpu_governor")
        if gov:
            color = "\033[32m" if gov == "performance" else "\033[33m"
            print(f"    CPU governor: {color}{gov}\033[0m")
        # Linux: CPU freq
        freq = settings.get("cpu_freq_mhz")
        max_freq = settings.get("cpu_max_freq_mhz")
        if freq:
            print(f"    CPU freq: {freq} MHz", end="")
            if max_freq:
                pct = freq / max_freq * 100
                print(f" / {max_freq} MHz ({pct:.0f}%)", end="")
            print()
        # Linux: swappiness
        swap = settings.get("swappiness")
        if swap is not None:
            color = "\033[32m" if swap <= 10 else "\033[33m" if swap <= 30 else "\033[31m"
            print(f"    Swappiness: {color}{swap}\033[0m")
        # Linux: scheduler granularity
        gran = settings.get("sched_min_granularity_ms")
        if gran is not None:
            color = "\033[32m" if gran <= 1.0 else "\033[33m"
            print(f"    Sched granularity: {color}{gran:.1f}ms\033[0m")

    # Network details
    network = status.get("network", {})
    net_settings = network.get("settings", {})
    if net_settings:
        print(f"\n  Network:")
        # Windows: Nagle
        total_iface = net_settings.get("total_interfaces", 0)
        disabled = net_settings.get("nagle_disabled_interfaces", 0)
        if total_iface > 0:
            color = "\033[32m" if disabled == total_iface else "\033[33m"
            print(f"    Nagle disabled: {color}{disabled}/{total_iface} interfaces\033[0m")
        # Windows: autotuning
        autotuning = net_settings.get("autotuning")
        if autotuning:
            color = "\033[32m" if autotuning in ("restricted", "disabled") else "\033[33m"
            print(f"    Auto-tuning: {color}{autotuning}\033[0m")
        # Linux: congestion control
        cc = net_settings.get("congestion_control")
        if cc:
            color = "\033[32m" if cc == "bbr" else "\033[33m"
            print(f"    Congestion: {color}{cc}\033[0m")
        # Linux: TCP fast open
        tfo = net_settings.get("tcp_fastopen")
        if tfo is not None:
            color = "\033[32m" if tfo >= 3 else "\033[33m"
            print(f"    TCP Fast Open: {color}{tfo}\033[0m")
        # Linux: low latency
        ll = net_settings.get("tcp_low_latency")
        if ll is not None:
            color = "\033[32m" if ll else "\033[33m"
            print(f"    Low latency mode: {color}{'on' if ll else 'off'}\033[0m")
        # Common: ECN
        ecn = net_settings.get("ecn")
        if ecn:
            print(f"    ECN: {ecn}")

    # GPU details
    gpu = status.get("gpu", {})
    gpu_settings = gpu.get("settings", {})
    if gpu_settings:
        print(f"\n  GPU:")
        vendor = gpu_settings.get("vendor", "unknown")
        print(f"    Vendor: {vendor}")
        # NVIDIA details
        nv_name = gpu_settings.get("nvidia_name")
        if nv_name:
            print(f"    Model: {nv_name}")
        # AMD perf level
        amd_level = gpu_settings.get("amd_perf_level")
        if amd_level:
            color = "\033[32m" if amd_level in ("high", "profile_peak") else "\033[33m"
            print(f"    Perf level: {color}{amd_level}\033[0m")
        amd_sclk = gpu_settings.get("amd_current_sclk")
        if amd_sclk:
            print(f"    SCLK: {amd_sclk}")
        # Temp
        temp = gpu_settings.get("gpu_temp_c")
        if temp is not None:
            color = "\033[32m" if temp < 70 else "\033[33m" if temp < 85 else "\033[31m"
            print(f"    Temp: {color}{temp}C\033[0m")
        # Power
        power_w = gpu_settings.get("gpu_power_w")
        if power_w is not None:
            print(f"    Power: {power_w:.0f}W")
        # HAGS (Windows)
        hags = gpu_settings.get("hags_enabled")
        if hags is not None:
            print(f"    HAGS: {'enabled' if hags else 'disabled'}")

    # Process details
    proc = status.get("process", {})
    proc_settings = proc.get("settings", {})
    if proc_settings:
        print(f"\n  Process:")
        # Linux: THP
        thp = proc_settings.get("thp")
        if thp:
            color = "\033[32m" if thp == "madvise" else "\033[33m"
            print(f"    THP: {color}{thp}\033[0m")
        # Linux: NMI watchdog
        wd = proc_settings.get("nmi_watchdog")
        if wd is not None:
            color = "\033[32m" if not wd else "\033[33m"
            print(f"    NMI watchdog: {color}{'on' if wd else 'off'}\033[0m")
        # Linux: GameMode
        gm = proc_settings.get("gamemode")
        if gm is not None:
            color = "\033[32m" if gm else "\033[33m"
            print(f"    GameMode: {color}{'active' if gm else 'inactive'}\033[0m")
        # Windows: background apps
        bg = proc_settings.get("background_apps_disabled")
        if bg is not None:
            print(f"    Background apps: {'disabled' if bg else 'enabled'}")


def cmd_boost_profiles(args):
    """List available game profiles."""
    from mesh_boost.profiles.manager import ProfileManager

    mgr = ProfileManager()
    profiles = mgr.list_profiles()

    print(f"Available Game Profiles ({len(profiles)})")
    print("\u2500" * 50)

    by_genre = {}
    for p in profiles:
        genre = p.get("genre", "other")
        by_genre.setdefault(genre, []).append(p)

    for genre in sorted(by_genre):
        print(f"\n  {genre.upper()}:")
        for p in by_genre[genre]:
            tier_badge = " \033[33m[PRO]\033[0m" if p["tier"] == "pro" else ""
            exes = ", ".join(p["exe_names"][:3]) if p["exe_names"] else "generic"
            print(f"    {p['name']}{tier_badge}  ({exes})")

    active = mgr.active_profile
    if active:
        print(f"\n  Active profile: \033[32m{active}\033[0m")


def cmd_boost_detect(args):
    """Detect running games and show matching profiles."""
    from mesh_boost.detector.game_detector import GameDetector
    from mesh_boost.profiles.manager import ProfileManager

    detector = GameDetector()
    mgr = ProfileManager()

    print("Scanning for games...")
    games = detector.detect_running()

    if not games:
        games = detector.detect_running_simple()

    if not games:
        print("  No known games detected")
        # Show installed launchers
        launchers = detector.get_installed_launchers() if hasattr(detector, 'get_installed_launchers') else []
        if launchers:
            print(f"\n  Installed launchers: {', '.join(launchers)}")
        # Show Steam games
        steam = detector.get_steam_games()
        if steam:
            print(f"  Steam games installed: {len(steam)}")
            for g in steam[:10]:
                print(f"    - {g}")
            if len(steam) > 10:
                print(f"    ... and {len(steam) - 10} more")
        return

    print(f"\n  Found {len(games)} game(s):")
    for g in games:
        if g.get("genre") == "launcher":
            continue
        name = g.get("name", "?")
        pid = g.get("pid", "?")
        genre = g.get("genre", "?")

        # Check for matching profile
        exe = g.get("process_name", "")
        profile = mgr.match_game(exe, genre)

        profile_str = f" \033[32m-> profile: {profile.name}\033[0m" if profile else " \033[33m(no profile)\033[0m"
        print(f"    {name} (PID {pid}, {genre}){profile_str}")
