import sys
import requests
from pathlib import Path
from typing import Any, Dict, Sequence

# Add project root to sys.path
root = Path(__file__).resolve().parent.parent
if str(root) not in sys.path:
    sys.path.insert(0, str(root))

from cmdlet._shared import Cmdlet
from SYS.config import load_config
from SYS.result_table import Table
from API import zerotier as zt

def exec_zerotier(result: Any, args: Sequence[str], config: Dict[str, Any]) -> int:
    # Use provided config or fall back to CWD load
    cfg = config if config else load_config(Path.cwd())
    
    table = Table("ZeroTier Status")
    
    # 1. Local Hub Status
    row = table.add_row()
    row.add_column("TYPE", "HOST")
    row.add_column("NAME", "localhost")
    
    # Try to get node ID via CLI info
    node_id = "???"
    try:
        if hasattr(zt, "_run_cli_json"):
            info = zt._run_cli_json("info", "-j")
            node_id = info.get("address", "???")
    except:
        pass
    row.add_column("ID", node_id)
    
    # Check if local server is responsive
    try:
        # endpoint is /health for remote_storage_server
        # We try 127.0.0.1 first with a more generous timeout
        # Using a list of potential local hits to be robust against Windows networking quirks
        import socket
        
        def get_local_ip():
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                s.connect(("8.8.8.8", 80))
                ip = s.getsockname()[0]
                s.close()
                return ip
            except:
                return None

        hosts = ["127.0.0.1", "localhost"]
        local_ip = get_local_ip()
        if local_ip:
            hosts.append(local_ip)
            
        success = False
        last_err = ""
        
        # Try multiple times if server just started
        import time
        for attempt in range(3):
            for host in hosts:
                try:
                    resp = requests.get(f"http://{host}:999/health", timeout=3, proxies={"http": None, "https": None})
                    if resp.status_code == 200:
                        row.add_column("STATUS", "ONLINE")
                        row.add_column("ADDRESS", f"{host}:999")
                        row.add_column("DETAIL", f"Serving {cfg.get('active_store', 'default')}")
                        success = True
                        break
                    elif resp.status_code == 401:
                        row.add_column("STATUS", "Serving (Locked)")
                        row.add_column("ADDRESS", f"{host}:999")
                        row.add_column("DETAIL", "401 Unauthorized - API Key required")
                        success = True
                        break
                except Exception as e:
                    last_err = str(e)
                    continue
            if success:
                break
            time.sleep(1) # Wait between attempts
        
        if not success:
            row.add_column("STATUS", "OFFLINE")
            row.add_column("ADDRESS", "127.0.0.1:999")
            row.add_column("DETAIL", f"Server not responding on port 999. Last attempt ({hosts[-1]}): {last_err}")

    except Exception as e:
        row.add_column("STATUS", "OFFLINE")
        row.add_column("ADDRESS", "127.0.0.1:999")
        row.add_column("DETAIL", f"Status check failed: {e}")

    # 2. Add Networks
    if zt.is_available():
        try:
            networks = zt.list_networks()
            for net in networks:
                row = table.add_row()
                row.add_column("TYPE", "NETWORK")
                row.add_column("NAME", getattr(net, "name", "Unnamed"))
                row.add_column("ID", getattr(net, "id", ""))
                
                status = getattr(net, "status", "OK")
                assigned = getattr(net, "assigned_addresses", [])
                ip_str = assigned[0] if assigned else ""
                
                row.add_column("STATUS", status)
                row.add_column("ADDRESS", ip_str)
        except Exception as e:
            row = table.add_row()
            row.add_column("TYPE", "ERROR")
            row.add_column("DETAIL", f"Failed to list networks: {e}")
    else:
        row = table.add_row()
        row.add_column("TYPE", "SYSTEM")
        row.add_column("NAME", "ZeroTier")
        row.add_column("STATUS", "NOT FOUND")
        row.add_column("DETAIL", "zerotier-cli not in path")

    # Output
    try:
        from cmdnat.out_table import TableOutput
        TableOutput().render(table)
    except Exception:
        # Fallback for raw CLI
        print(f"\n--- {table.title} ---")
        for r in table.rows:
            # Use the get_column method from ResultRow
            t = r.get_column("TYPE") or ""
            n = r.get_column("NAME") or ""
            s = r.get_column("STATUS") or ""
            a = r.get_column("ADDRESS") or ""
            id = r.get_column("ID") or ""
            d = r.get_column("DETAIL") or ""
            print(f"[{t:7}] {n:15} | {s:15} | {a:20} | {id} | {d}")
        print("-" * 100)
    
    return 0

CMDLET = Cmdlet(
    name=".zerotier",
    summary="Check ZeroTier node and hosting status",
    usage=".zerotier",
    exec=exec_zerotier,
)

if __name__ == "__main__":
    exec_zerotier(None, sys.argv[1:], {})