"""
Setup Wizard & Config Loader for El Gringo
============================================

Two entry points:
- load_config()  — reads ~/.elgringo/config.yml, injects API keys into os.environ
- run_setup()    — interactive wizard that tests keys and writes config
"""

import os
import subprocess
import sys
from pathlib import Path

CONFIG_DIR = Path.home() / ".elgringo"
CONFIG_FILE = CONFIG_DIR / "config.yml"

# Provider definitions: (env_var, display_name, key_prefix_hint)
PROVIDERS = [
    ("OPENAI_API_KEY", "OpenAI (ChatGPT)", "sk-"),
    ("GEMINI_API_KEY", "Google (Gemini)", "AI"),
    ("XAI_API_KEY", "xAI (Grok)", "xai-"),
    ("GROQ_API_KEY", "Groq (fast inference)", "gsk_"),
    ("ANTHROPIC_API_KEY", "Anthropic (Claude)", "sk-ant-"),
]


def _parse_yaml_simple(text: str) -> dict:
    """Minimal YAML parser for flat key-value and one-level nested dicts."""
    result = {}
    current_section = None
    for line in text.splitlines():
        stripped = line.strip()
        if not stripped or stripped.startswith("#"):
            continue
        indent = len(line) - len(line.lstrip())
        if stripped.endswith(":") and indent == 0:
            current_section = stripped[:-1]
            result[current_section] = {}
        elif ":" in stripped and indent > 0 and current_section:
            k, v = stripped.split(":", 1)
            v = v.strip().strip("'\"")
            if v:
                result[current_section][k.strip()] = v
        elif ":" in stripped and indent == 0:
            k, v = stripped.split(":", 1)
            v = v.strip().strip("'\"")
            if v:
                result[k.strip()] = v
    return result


def _needs_quoting(value: str) -> bool:
    """Check if a YAML value needs quoting (contains special chars)."""
    if not isinstance(value, str):
        return False
    # Quote if contains YAML-special characters
    return any(c in value for c in ':{}[],"\'|>&*!%#`@')


def _write_yaml_simple(config: dict) -> str:
    """Write a simple YAML string from a dict."""
    lines = []
    for key, value in config.items():
        if isinstance(value, dict):
            lines.append(f"{key}:")
            for k, v in value.items():
                if v is True:
                    lines.append(f"  {k}: true")
                elif v is False:
                    lines.append(f"  {k}: false")
                elif _needs_quoting(v):
                    lines.append(f"  {k}: '{v}'")
                else:
                    lines.append(f"  {k}: {v}")
        else:
            if value is True:
                lines.append(f"{key}: true")
            elif value is False:
                lines.append(f"{key}: false")
            elif _needs_quoting(value):
                lines.append(f"{key}: '{value}'")
            else:
                lines.append(f"{key}: {value}")
    return "\n".join(lines) + "\n"


def load_config() -> dict:
    """Load ~/.elgringo/config.yml and inject API keys into os.environ.

    Falls back gracefully if no config file exists (uses existing env vars).
    Returns the parsed config dict.
    """
    if not CONFIG_FILE.exists():
        return {}

    try:
        text = CONFIG_FILE.read_text()
    except Exception:
        return {}

    # Try pyyaml first, fall back to simple parser
    try:
        import yaml
        config = yaml.safe_load(text) or {}
    except ImportError:
        config = _parse_yaml_simple(text)

    # Inject API keys into environment (don't overwrite existing)
    api_keys = config.get("api_keys", {})
    key_map = {
        "openai": "OPENAI_API_KEY",
        "gemini": "GEMINI_API_KEY",
        "xai": "XAI_API_KEY",
        "groq": "GROQ_API_KEY",
        "anthropic": "ANTHROPIC_API_KEY",
    }
    for config_name, env_name in key_map.items():
        value = api_keys.get(config_name)
        if value and not os.environ.get(env_name):
            os.environ[env_name] = value

    # Inject cloud API settings into environment
    api_url = config.get("api_url", "")
    api_key = config.get("api_key", "")
    if api_url and not os.environ.get("ELGRINGO_API_URL"):
        os.environ["ELGRINGO_API_URL"] = api_url
    if api_key and not os.environ.get("ELGRINGO_API_KEY"):
        os.environ["ELGRINGO_API_KEY"] = api_key

    return config


def _test_openai_key(key: str) -> bool:
    """Test an OpenAI API key with a lightweight models list call."""
    try:
        import urllib.request
        import urllib.error
        req = urllib.request.Request(
            "https://api.openai.com/v1/models",
            headers={"Authorization": f"Bearer {key}"},
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            return resp.status == 200
    except Exception:
        return False


def _test_gemini_key(key: str) -> bool:
    """Test a Gemini API key."""
    try:
        import urllib.request
        url = f"https://generativelanguage.googleapis.com/v1beta/models?key={key}"
        with urllib.request.urlopen(url, timeout=10) as resp:
            return resp.status == 200
    except Exception:
        return False


def _test_xai_key(key: str) -> bool:
    """Test an xAI API key."""
    try:
        import urllib.request
        req = urllib.request.Request(
            "https://api.x.ai/v1/models",
            headers={"Authorization": f"Bearer {key}"},
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            return resp.status == 200
    except Exception:
        return False


def _test_groq_key(key: str) -> bool:
    """Test a Groq API key."""
    try:
        import urllib.request
        req = urllib.request.Request(
            "https://api.groq.com/openai/v1/models",
            headers={"Authorization": f"Bearer {key}"},
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            return resp.status == 200
    except Exception:
        return False


def _test_anthropic_key(key: str) -> bool:
    """Test an Anthropic API key."""
    try:
        import urllib.request
        req = urllib.request.Request(
            "https://api.anthropic.com/v1/models",
            headers={
                "x-api-key": key,
                "anthropic-version": "2023-06-01",
            },
        )
        with urllib.request.urlopen(req, timeout=10) as resp:
            return resp.status == 200
    except Exception:
        return False


def _detect_ollama() -> list:
    """Detect running Ollama models."""
    try:
        result = subprocess.run(
            ["ollama", "list"], capture_output=True, text=True, timeout=5
        )
        if result.returncode != 0:
            return []
        models = []
        for line in result.stdout.strip().splitlines()[1:]:  # skip header
            name = line.split()[0] if line.strip() else ""
            if name:
                models.append(name)
        return models
    except Exception:
        return []


def _detect_mlx() -> bool:
    """Check if mlx_lm is available."""
    try:
        import importlib
        importlib.import_module("mlx_lm")
        return True
    except ImportError:
        return False


def run_setup():
    """Interactive setup wizard. Prompts for API keys, tests them, writes config."""
    print("\n\033[1m\033[96m" + "=" * 50 + "\033[0m")
    print("\033[1m  El Gringo — Setup Wizard\033[0m")
    print("\033[1m\033[96m" + "=" * 50 + "\033[0m\n")
    print("  Configure your AI agents. Press Enter to skip any provider.\n")

    api_keys = {}
    cloud_count = 0

    testers = {
        "OPENAI_API_KEY": _test_openai_key,
        "GEMINI_API_KEY": _test_gemini_key,
        "XAI_API_KEY": _test_xai_key,
        "GROQ_API_KEY": _test_groq_key,
        "ANTHROPIC_API_KEY": _test_anthropic_key,
    }

    config_name_map = {
        "OPENAI_API_KEY": "openai",
        "GEMINI_API_KEY": "gemini",
        "XAI_API_KEY": "xai",
        "GROQ_API_KEY": "groq",
        "ANTHROPIC_API_KEY": "anthropic",
    }

    for env_var, display_name, prefix_hint in PROVIDERS:
        existing = os.environ.get(env_var, "")
        existing_hint = f" [\033[2mcurrent: {existing[:8]}...]\033[0m" if existing else ""

        key = input(f"  {display_name}{existing_hint}\n  API key (starts with {prefix_hint}): ").strip()

        if not key and existing:
            key = existing
        if not key:
            print("  \033[2mSkipped\033[0m\n")
            continue

        # Test the key
        tester = testers.get(env_var)
        sys.stdout.write("  Testing... ")
        sys.stdout.flush()
        if tester and tester(key):
            print("\033[92mOK\033[0m\n")
        elif tester:
            print("\033[93mfailed (key saved anyway)\033[0m\n")
        else:
            print("\033[2msaved\033[0m\n")

        config_name = config_name_map[env_var]
        api_keys[config_name] = key
        cloud_count += 1

    # Detect local models
    print("  \033[1mDetecting local models...\033[0m")
    local_count = 0

    ollama_models = _detect_ollama()
    if ollama_models:
        print(f"  \033[92mOllama:\033[0m {', '.join(ollama_models[:5])}")
        local_count += len(ollama_models)
    else:
        print("  \033[2mOllama: not running (install: https://ollama.com)\033[0m")

    has_mlx = _detect_mlx()
    if has_mlx:
        print("  \033[92mMLX:\033[0m available (Apple Silicon)")
        local_count += 1
    else:
        print("  \033[2mMLX: not available\033[0m")

    # Build config
    config = {
        "api_keys": api_keys,
        "defaults": {
            "mode": "auto",
            "local_first": "true" if local_count > 0 and cloud_count == 0 else "false",
        },
    }

    # Write config with restricted permissions (contains API keys)
    CONFIG_DIR.mkdir(parents=True, exist_ok=True)
    try:
        import yaml
        CONFIG_FILE.write_text(yaml.dump(config, default_flow_style=False, sort_keys=False))
    except ImportError:
        CONFIG_FILE.write_text(_write_yaml_simple(config))
    try:
        CONFIG_DIR.chmod(0o700)
        CONFIG_FILE.chmod(0o600)
    except OSError:
        pass

    # Summary
    _total = cloud_count + (1 if ollama_models else 0) + (1 if has_mlx else 0)
    print(f"\n  \033[1m\033[92mDone!\033[0m Config saved to {CONFIG_FILE}")
    print(f"  {cloud_count} cloud agent{'s' if cloud_count != 1 else ''} + {local_count} local model{'s' if local_count != 1 else ''} configured")
    print("\n  Next steps:")
    print("    elgringo ask \"hello world\"       # Test it")
    print("    elgringo mcp install              # Add to Claude Code")
    print("    elgringo models                   # See all agents")
    print()
