"""Click wrappers: tests + diagnose groups — split from ctl.py."""
from __future__ import annotations

import os
import sys
import json
import socket
import subprocess
from pathlib import Path
from urllib.parse import urlparse
from typing import NamedTuple

import click
import httpx

from proxym.cli import diagnostics as diag_cli
from proxym.cli._groups._shared import (
    make_args as _make_args,
    register_commands,
    passthrough,
    passthrough_fmt,
)


# ── Tests group ──────────────────────────────────────────────

@click.group(name="tests")
def tests():
    """Run system diagnostics."""
    pass


register_commands(tests, [
    ("vscode",      diag_cli.cmd_test_vscode,      "Test VS Code Web connectivity."),
    ("proxy",       diag_cli.cmd_test_proxy,        "Test LLM proxy connectivity."),
    ("agent-setup", diag_cli.cmd_test_agent_setup,  "Comprehensive agent readiness check."),
    ("agent",       diag_cli.cmd_test_agent,         "Test agent with a simple completion."),
], passthrough)

register_commands(tests, [
    ("status",     diag_cli.cmd_tests_status,     "Run all diagnostic tests."),
    ("providers",  diag_cli.cmd_test_providers,   "Check configured LLM providers."),
    ("extensions", diag_cli.cmd_test_extensions,  "Check installed VS Code extensions."),
], passthrough_fmt)


# ── Diagnose alias group ─────────────────────────────────────

@click.group(name="diagnose")
def diagnose():
    """Run diagnostics to verify system health (alias for 'tests')."""
    pass


register_commands(diagnose, [
    ("proxy",  diag_cli.cmd_test_proxy,   "Test proxy connectivity."),
    ("vscode", diag_cli.cmd_test_vscode,  "Test VS Code Web status."),
    ("agent",  diag_cli.cmd_test_agent,   "Test agent setup + completion."),
], passthrough)

register_commands(diagnose, [
    ("all",       diag_cli.cmd_tests_status,   "Run all diagnostic tests."),
    ("providers", diag_cli.cmd_test_providers, "Test provider configuration."),
], passthrough_fmt)


@diagnose.command(name="test")
@click.argument("test_name")
@click.pass_context
def diagnose_one(ctx: click.Context, test_name: str):
    """Run a specific test (vscode|proxy|roo|extensions|providers|copilot|agent-setup|agent)."""
    from proxym.cli._client import make_client, print_json
    args = _make_args(ctx)
    c = make_client(args.proxy, args.key)
    r = c.get(f"/tests/{test_name}", timeout=30)
    print_json(r.json())


# ── Doctor command ───────────────────────────────────────────

class CheckResult(NamedTuple):
    name: str
    status: str
    message: str
    fix: str | None = None


def _load_env_vars() -> dict[str, str]:
    """Load environment variables from .env."""
    env_vars = {}
    env_path = Path(".env")
    if env_path.exists():
        content = env_path.read_text()
        for line in content.split('\n'):
            line = line.strip()
            if line and not line.startswith('#') and '=' in line:
                key, _, value = line.partition('=')
                env_vars[key] = value.strip().strip('"\'')
    return env_vars


def _run_doctor_checks() -> list[CheckResult]:
    """Run comprehensive system diagnostics."""
    checks = []
    env_vars = _load_env_vars()
    
    # Check .env file
    env_path = Path(".env")
    if not env_path.exists():
        checks.append(CheckResult(".env file", "error", ".env file not found", 
            "Create .env: cp .env.example .env && edit with your API keys"))
    elif not env_path.read_text().strip():
        checks.append(CheckResult(".env file", "error", ".env file is empty",
            "Add required configuration: AI_PROXY_MASTER_KEY and LLM provider keys"))
    else:
        checks.append(CheckResult(".env file", "ok", f"Loaded {len(env_vars)} variables"))
    
    # Check required config
    if not env_vars.get("AI_PROXY_MASTER_KEY"):
        checks.append(CheckResult("Master key", "error", "AI_PROXY_MASTER_KEY missing",
            "Add to .env: AI_PROXY_MASTER_KEY=sk-proxy-..."))
    else:
        key = env_vars.get("AI_PROXY_MASTER_KEY", "")
        if key.startswith("sk-or-"):
            checks.append(CheckResult("Master key", "warning", "External OpenRouter key - SSE may not work",
                "Generate local key: proxym keys generate"))
        elif not key.startswith("sk-proxy-"):
            checks.append(CheckResult("Master key", "warning", "Key format may be invalid",
                "Generate new key: proxym keys generate"))
        else:
            checks.append(CheckResult("Master key", "ok", "Local key format"))
    
    # Check LLM providers
    providers = ["OPENROUTER_API_KEY", "ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GOOGLE_AI_API_KEY", "MISTRAL_API_KEY"]
    configured = [p.replace("_API_KEY", "").replace("_", " ").title() for p in providers if env_vars.get(p)]
    if not configured:
        checks.append(CheckResult("LLM providers", "error", "No provider API keys configured",
            "Add at least one: OPENROUTER_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, etc."))
    else:
        checks.append(CheckResult("LLM providers", "ok", f"Configured: {', '.join(configured)}"))
    
    # Check proxy server
    proxy_url = env_vars.get("AI_PROXY_URL", "http://localhost:4000")
    try:
        parsed = urlparse(proxy_url)
        host = parsed.hostname or "localhost"
        port = parsed.port or 4000
        
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(2)
        result = sock.connect_ex((host, port))
        sock.close()
        
        if result != 0:
            checks.append(CheckResult("Proxy server", "error", f"Not reachable at {host}:{port}",
                f"Start server: proxym serve (expected on {proxy_url})"))
        else:
            try:
                r = httpx.get(f"{proxy_url}/health", timeout=5)
                if r.status_code == 200:
                    version = r.json().get("version", "unknown")
                    checks.append(CheckResult("Proxy server", "ok", f"Running (v{version})"))
                else:
                    checks.append(CheckResult("Proxy server", "warning", f"Health check failed (HTTP {r.status_code})",
                        "Check server logs"))
            except Exception:
                checks.append(CheckResult("Proxy server", "warning", "Port open but HTTP failed",
                    "Server may be starting up - wait and retry"))
    except Exception as e:
        checks.append(CheckResult("Proxy server", "error", f"Check failed: {e}",
            "Check AI_PROXY_URL format"))
    
    # Check data directory
    data_dir = Path("data")
    if not data_dir.exists():
        checks.append(CheckResult("Data directory", "warning", "Directory not found",
            "Create: mkdir data"))
    elif not os.access(data_dir, os.W_OK):
        checks.append(CheckResult("Data directory", "error", "Not writable",
            "Fix permissions: chmod 755 data && chown $USER data"))
    else:
        checks.append(CheckResult("Data directory", "ok", f"Ready ({len(list(data_dir.iterdir()))} files)"))
    
    # Check git repository
    git_dir = Path(".git")
    if not git_dir.exists():
        checks.append(CheckResult("Git repository", "warning", "Not a git repo - dashboard git sync won't work",
            "Initialize: git init && git add . && git commit -m 'initial'"))
    else:
        checks.append(CheckResult("Git repository", "ok", "Repository present"))
    
    return checks


def _print_doctor_report(checks: list[CheckResult]):
    """Print diagnostic report."""
    print("\n" + "═" * 60)
    print("  🔍 PROXYM SYSTEM DIAGNOSTICS")
    print("═" * 60 + "\n")
    
    ok = [c for c in checks if c.status == "ok"]
    warnings = [c for c in checks if c.status == "warning"]
    errors = [c for c in checks if c.status == "error"]
    
    if errors:
        print(f"\033[0;31m✗ {len(errors)} CRITICAL ISSUE(S)\033[0m")
        for check in errors:
            print(f"\n  \033[1m{check.name}\033[0m")
            print(f"  → {check.message}")
            if check.fix:
                print(f"  \033[2m  Fix: {check.fix}\033[0m")
        print()
    
    if warnings:
        print(f"\033[0;33m⚠ {len(warnings)} WARNING(S)\033[0m")
        for check in warnings:
            print(f"\n  \033[1m{check.name}\033[0m")
            print(f"  → {check.message}")
            if check.fix:
                print(f"  \033[2m  Fix: {check.fix}\033[0m")
        print()
    
    if ok:
        print(f"\033[0;32m✓ {len(ok)} CHECK(S) PASSED\033[0m")
        for check in ok:
            print(f"  • {check.name}: {check.message}")
        print()
    
    print("─" * 60)
    if errors:
        print("\033[0;31mStatus: NOT READY - fix critical issues\033[0m")
    elif warnings:
        print("\033[0;33mStatus: FUNCTIONAL with warnings\033[0m")
    else:
        print("\033[0;32mStatus: ALL SYSTEMS OPERATIONAL\033[0m")
    print("─" * 60 + "\n")


@click.command(name="doctor")
def doctor_cmd():
    """Comprehensive system diagnostics — check configuration and health.
    
    Checks:
      • .env file and API keys
      • Proxy server connectivity
      • LLM provider configuration
      • Data directory and git repository
    
    Run this first if you're experiencing issues.
    """
    checks = _run_doctor_checks()
    _print_doctor_report(checks)
    
    errors = [c for c in checks if c.status == "error"]
    if errors:
        print("Quick actions:")
        print("  proxym keys init     # Initialize API keys")
        print("  proxym serve         # Start the proxy server")
        sys.exit(1)
