#!/usr/bin/env python3
"""Interactive setup wizard for second-opinion-mcp."""
import sys
import platform

try:
    import questionary
    from questionary import Style
except ImportError:
    print("Error: questionary not installed. Run: pip install questionary")
    sys.exit(1)

import keyring
from keyring.errors import NoKeyringError

# Provider configurations
PROVIDERS = {
    "deepseek": {
        "name": "DeepSeek V3.2",
        "description": "DeepSeek Reasoner with chain-of-thought reasoning",
        "keyring_service": "second-opinion",
        "keyring_name": "deepseek",
        "key_hint": "https://platform.deepseek.com",
        "key_prefix": "sk-",
    },
    "moonshot": {
        "name": "Kimi K2.5 (Moonshot)",
        "description": "Moonshot AI's Kimi with thinking mode",
        "keyring_service": "second-opinion",
        "keyring_name": "moonshot",
        "key_hint": "https://platform.moonshot.cn",
        "key_prefix": None,
    },
    "openrouter": {
        "name": "OpenRouter",
        "description": "Access 300+ models via unified API",
        "keyring_service": "second-opinion",
        "keyring_name": "openrouter",
        "key_hint": "https://openrouter.ai/keys",
        "key_prefix": "sk-or-",
    },
}

# Custom style for questionary
custom_style = Style([
    ("qmark", "fg:cyan bold"),
    ("question", "bold"),
    ("answer", "fg:cyan"),
    ("pointer", "fg:cyan bold"),
    ("highlighted", "fg:cyan bold"),
    ("selected", "fg:green"),
])


def check_keyring_available() -> tuple[bool, str]:
    """Check if keyring backend is available and working."""
    try:
        # Try to access keyring - this will fail if no backend
        backend = keyring.get_keyring()
        backend_name = str(type(backend).__name__)

        # Check for null/fail backends
        if "Null" in backend_name or "Fail" in backend_name:
            return False, backend_name

        # Try a test write/read/delete to verify it works
        test_service = "second-opinion-test"
        test_key = "connectivity-check"
        try:
            keyring.set_password(test_service, test_key, "test")
            result = keyring.get_password(test_service, test_key)
            keyring.delete_password(test_service, test_key)
            if result != "test":
                return False, backend_name
        except Exception:
            return False, backend_name

        return True, backend_name
    except NoKeyringError:
        return False, "NoKeyringError"
    except Exception as e:
        return False, str(e)


def print_keyring_setup_instructions():
    """Print instructions for setting up keyring on different platforms."""
    print()
    print("=" * 60)
    print("  Keyring Backend Required")
    print("=" * 60)
    print()
    print("second-opinion-mcp stores API keys securely in your system keyring.")
    print("A keyring backend must be installed and configured first.")
    print()

    system = platform.system()

    if system == "Linux":
        print("For Linux, install one of these backends:")
        print()
        print("  Option 1 - Secret Service (GNOME/KDE desktop):")
        print("    sudo apt install gnome-keyring  # or kde-wallet")
        print("    pip install secretstorage")
        print()
        print("  Option 2 - Encrypted file (headless/server):")
        print("    pip install keyrings.alt")
        print("    mkdir -p ~/.local/share/python_keyring")
        print("    cat > ~/.local/share/python_keyring/keyringrc.cfg << 'EOF'")
        print("    [backend]")
        print("    default-keyring=keyrings.alt.file.EncryptedKeyring")
        print("    EOF")
        print()
        print("  Then run 'second-opinion-mcp setup' again.")

    elif system == "Darwin":
        print("For macOS, keyring should work automatically with Keychain.")
        print("If you see this error, try:")
        print()
        print("  pip install keyring --upgrade")
        print()
        print("Then run 'second-opinion-mcp setup' again.")

    else:
        print("For Windows, keyring should work automatically with Credential Manager.")
        print("If you see this error, try:")
        print()
        print("  pip install keyring --upgrade")
        print()
        print("Then run 'second-opinion-mcp setup' again.")

    print()


def print_manual_setup_instructions(providers: list[str] | None = None):
    """Print instructions for manual keyring setup."""
    print()
    print("=" * 60)
    print("  Manual API Key Setup")
    print("=" * 60)
    print()
    print("IMPORTANT: You must configure at least 2 providers for the")
    print("'consensus' tool to work. Single-provider mode is limited.")
    print()
    print("Run these commands to store your API keys:")
    print()

    target_providers = providers if providers else list(PROVIDERS.keys())

    for provider in target_providers:
        config = PROVIDERS[provider]
        print(f"  # {config['name']} - Get key at {config['key_hint']}")
        print(f"  python3 -c \"import keyring; keyring.set_password('{config['keyring_service']}', '{config['keyring_name']}', 'YOUR_API_KEY')\"")
        print()

    print("To verify your keys are stored:")
    print()
    print("  python3 -c \"import keyring; print('deepseek:', bool(keyring.get_password('second-opinion', 'deepseek'))); print('moonshot:', bool(keyring.get_password('second-opinion', 'moonshot')))\"")
    print()
    print("After configuring keys, register with Claude Code:")
    print()

    if providers and len(providers) >= 1:
        providers_str = ",".join(providers)
    else:
        providers_str = "deepseek,moonshot"

    print(f"  claude mcp add -s user second-opinion -e SECOND_OPINION_PROVIDERS=\"{providers_str}\" -- second-opinion-mcp")
    print()


def check_existing_keys() -> dict[str, bool]:
    """Check which providers already have API keys configured."""
    existing = {}
    for provider, config in PROVIDERS.items():
        try:
            key = keyring.get_password(config["keyring_service"], config["keyring_name"])
            existing[provider] = bool(key)
        except Exception:
            existing[provider] = False
    return existing


def count_configured_providers() -> int:
    """Count how many providers have API keys configured."""
    return sum(1 for v in check_existing_keys().values() if v)


def store_api_key(provider: str, key: str) -> tuple[bool, str]:
    """Store API key in system keyring. Returns (success, error_message)."""
    config = PROVIDERS[provider]
    try:
        keyring.set_password(config["keyring_service"], config["keyring_name"], key)
        return True, ""
    except Exception as e:
        return False, str(e)


def validate_api_key(provider: str, key: str) -> tuple[bool, str]:
    """Basic validation of API key format."""
    if not key or not key.strip():
        return False, "API key cannot be empty"

    config = PROVIDERS[provider]
    key = key.strip()

    if config["key_prefix"] and not key.startswith(config["key_prefix"]):
        return False, f"Key should start with '{config['key_prefix']}'"

    if len(key) < 20:
        return False, "Key seems too short"

    return True, ""


def get_registration_command(selected_providers: list[str]) -> str:
    """Generate the registration command for Claude Code CLI."""
    providers_env = ",".join(selected_providers)
    return f'claude mcp add -s user second-opinion -e SECOND_OPINION_PROVIDERS="{providers_env}" -- second-opinion-mcp'


def get_desktop_config(selected_providers: list[str]) -> str:
    """Generate Claude Desktop configuration JSON."""
    providers_env = ",".join(selected_providers)

    return f'''{{
  "mcpServers": {{
    "second-opinion": {{
      "command": "second-opinion-mcp",
      "env": {{
        "SECOND_OPINION_PROVIDERS": "{providers_env}"
      }}
    }}
  }}
}}'''


def setup_wizard():
    """Interactive setup wizard for second-opinion-mcp."""
    print()
    print("=" * 60)
    print("  Second Opinion MCP - Setup Wizard")
    print("=" * 60)
    print()

    # Check keyring availability first
    keyring_ok, backend_info = check_keyring_available()

    if not keyring_ok:
        print(f"Keyring backend not available: {backend_info}")
        print_keyring_setup_instructions()
        print()
        print("Alternatively, choose 'Manual setup' to get CLI commands.")
        print()

        choice = questionary.select(
            "How would you like to proceed?",
            choices=[
                questionary.Choice("Manual setup (show CLI commands)", value="manual"),
                questionary.Choice("Exit and fix keyring first", value="exit"),
            ],
            style=custom_style,
        ).ask()

        if choice == "manual" or choice is None:
            print_manual_setup_instructions()
        return

    print("This wizard will help you configure API keys for AI providers.")
    print("Keys are stored securely in your system keyring.")
    print()

    # Check existing configuration
    existing = check_existing_keys()
    configured_count = sum(1 for v in existing.values() if v)

    if configured_count > 0:
        configured = [p for p, has_key in existing.items() if has_key]
        print(f"Already configured: {', '.join(configured)}")
        if configured_count < 2:
            print("Note: At least 2 providers required for 'consensus' tool.")
        print()

    # Setup method selection
    setup_method = questionary.select(
        "Setup method:",
        choices=[
            questionary.Choice("Interactive (enter keys now)", value="interactive"),
            questionary.Choice("Manual (show CLI commands)", value="manual"),
        ],
        style=custom_style,
    ).ask()

    if setup_method is None:
        print("Setup cancelled.")
        return

    if setup_method == "manual":
        # Ask which providers they want to configure
        choices = [
            questionary.Choice(
                f"{config['name']}" + (" (configured)" if existing.get(provider) else ""),
                value=provider,
                checked=not existing.get(provider)  # Pre-check unconfigured ones
            )
            for provider, config in PROVIDERS.items()
        ]

        selected = questionary.checkbox(
            "Select providers to configure:",
            choices=choices,
            style=custom_style,
        ).ask()

        if not selected:
            selected = list(PROVIDERS.keys())

        print_manual_setup_instructions(selected)
        return

    # Interactive setup
    choices = []
    for provider, config in PROVIDERS.items():
        label = config["name"]
        if existing.get(provider):
            label += " (configured)"
        choices.append(questionary.Choice(label, value=provider, checked=not existing.get(provider)))

    selected = questionary.checkbox(
        "Select providers to configure (at least 2 required for consensus):",
        choices=choices,
        style=custom_style,
        validate=lambda x: len(x) >= 1 or "Select at least one provider",
    ).ask()

    if not selected:
        print("Setup cancelled.")
        return

    # Warn about single provider
    total_will_have = len([p for p in selected if not existing.get(p)]) + configured_count
    if total_will_have < 2 and len(selected) < 2:
        print()
        print("WARNING: You need at least 2 providers for the 'consensus' tool.")
        print("With only 1 provider, only basic tools will be available.")
        proceed = questionary.confirm(
            "Continue anyway?",
            default=False,
            style=custom_style,
        ).ask()
        if not proceed:
            return setup_wizard()

    print()

    # Configure API keys
    keyring_error_shown = False
    for provider in selected:
        config = PROVIDERS[provider]

        if existing.get(provider):
            update = questionary.confirm(
                f"{config['name']} already configured. Update API key?",
                default=False,
                style=custom_style,
            ).ask()
            if not update:
                continue

        print(f"\n{config['name']}")
        print(f"  Get your key at: {config['key_hint']}")

        while True:
            key = questionary.password(
                "  Enter API key:",
                style=custom_style,
            ).ask()

            if key is None:
                print("  Skipped.")
                break

            valid, error = validate_api_key(provider, key)
            if not valid:
                print(f"  {error}")
                retry = questionary.confirm("Try again?", default=True, style=custom_style).ask()
                if not retry:
                    break
                continue

            success, store_error = store_api_key(provider, key.strip())
            if success:
                print("  Key stored successfully.")
                break
            else:
                print(f"  Error storing key: {store_error}")
                if not keyring_error_shown:
                    keyring_error_shown = True
                    print()
                    print("  Keyring storage failed. You may need to configure a backend.")
                    show_manual = questionary.confirm(
                        "  Show manual setup instructions?",
                        default=True,
                        style=custom_style,
                    ).ask()
                    if show_manual:
                        print_manual_setup_instructions(selected)
                        return
                break

    # Check final configuration
    final_existing = check_existing_keys()
    configured = [p for p, has_key in final_existing.items() if has_key]

    print()
    print("=" * 60)
    print("  Setup Complete!")
    print("=" * 60)
    print()

    if not configured:
        print("No API keys were configured.")
        print("Run 'second-opinion-mcp setup' to try again.")
        return

    print(f"Configured providers: {', '.join(configured)}")

    if len(configured) < 2:
        print()
        print("WARNING: Only 1 provider configured. The 'consensus' tool requires 2+.")
        print("Run 'second-opinion-mcp setup' to add more providers.")

    print()
    print("Register with Claude Code CLI:")
    print()
    print(f"  {get_registration_command(configured)}")
    print()

    # Show desktop config option
    show_desktop = questionary.confirm(
        "Show Claude Desktop configuration?",
        default=False,
        style=custom_style,
    ).ask()

    if show_desktop:
        print()
        print("Add this to your claude_desktop_config.json:")
        print()
        print(get_desktop_config(configured))
        print()
        if platform.system() == "Windows":
            print("Location: %APPDATA%\\Claude\\claude_desktop_config.json")
        elif platform.system() == "Darwin":
            print("Location: ~/Library/Application Support/Claude/claude_desktop_config.json")
        else:
            print("Location: ~/.config/Claude/claude_desktop_config.json")

    print()
    print("Test the server with:")
    print("  second-opinion-mcp")
    print()


if __name__ == "__main__":
    setup_wizard()
