"""
Interactive setup wizard.

Guides user through authentication setup.
Runs CLI commands directly - credentials never touch our code.
"""

import subprocess
import sys
import os
from typing import Optional

import questionary
from questionary import Style

from .config import Config, load_config, save_config, TeleportConfig
from .auth import AuthManager, AuthStatus


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


# ANSI colors
class Colors:
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RED = '\033[91m'
    BLUE = '\033[94m'
    BOLD = '\033[1m'
    END = '\033[0m'


def print_header(text: str):
    print(f"\n{Colors.BOLD}{Colors.BLUE}{text}{Colors.END}")
    print("─" * 50)


def print_status(name: str, ok: bool, detail: str = ""):
    icon = f"{Colors.GREEN}✓{Colors.END}" if ok else f"{Colors.RED}✗{Colors.END}"
    status = f"{Colors.GREEN}Ready{Colors.END}" if ok else f"{Colors.YELLOW}Setup needed{Colors.END}"
    detail_str = f" ({detail})" if detail else ""
    print(f"  {icon} {name:<20} {status}{detail_str}")


def prompt(question: str, default: str = None) -> str:
    """Prompt user for input with questionary."""
    try:
        result = questionary.text(
            question,
            default=default or "",
            style=custom_style
        ).ask()
        if result is None:
            print("\nSetup cancelled.")
            sys.exit(1)
        return result
    except (EOFError, KeyboardInterrupt):
        print("\nSetup cancelled.")
        sys.exit(1)


def prompt_choice(question: str, options: list[str], default: int = 1) -> int:
    """Prompt user to choose from options with arrow keys."""
    try:
        result = questionary.select(
            question,
            choices=options,
            default=options[default - 1] if default <= len(options) else options[0],
            style=custom_style,
            use_arrow_keys=True,
            use_jk_keys=True,  # vim-style j/k navigation too
        ).ask()

        if result is None:
            print("\nSetup cancelled.")
            sys.exit(1)

        return options.index(result) + 1
    except (EOFError, KeyboardInterrupt):
        print("\nSetup cancelled.")
        sys.exit(1)


def run_command(cmd: list[str], description: str) -> bool:
    """Run a command, showing output to user."""
    print(f"\n{Colors.BLUE}→ {description}{Colors.END}")
    print(f"  Running: {' '.join(cmd)}\n")

    try:
        # Run interactively so user can see output and complete any prompts
        result = subprocess.run(cmd)
        return result.returncode == 0
    except FileNotFoundError:
        print(f"{Colors.RED}Command not found: {cmd[0]}{Colors.END}")
        return False
    except KeyboardInterrupt:
        print("\nCommand interrupted.")
        return False


def setup_teleport(config: Config, status: AuthStatus) -> bool:
    """Guide user through Teleport setup."""
    print_header("Teleport Setup")

    if status.teleport_logged_in:
        print(f"  Already logged in as: {status.teleport_user}")
        reauth = questionary.confirm(
            "Re-authenticate?",
            default=False,
            style=custom_style
        ).ask()
        if not reauth:
            return True

    # Simple two-option choice
    auth_choice = questionary.select(
        "How do you login to Teleport?",
        choices=[
            "Username/Password",
            "Okta SSO",
        ],
        style=custom_style
    ).ask()

    if auth_choice is None:
        return False

    # Default proxy
    proxy = "edgescaleai.teleport.sh:443"
    cluster = "edgescaleai.teleport.sh"

    if auth_choice == "Username/Password":
        # Need to get username - use saved one as default
        default_user = config.teleport.username or ""
        username = prompt("Teleport username", default_user)
        if not username:
            print(f"{Colors.RED}Username is required{Colors.END}")
            return False

        config.teleport.auth_method = None
        config.teleport.username = username  # Save for next time
        config.teleport.proxy = proxy
        config.teleport.cluster = cluster

        # Build command with --user flag
        cmd = [
            "tsh", "login",
            f"--proxy={proxy}",
            f"--user={username}",
            cluster
        ]

        print(f"\n{Colors.YELLOW}You will be prompted for your password.{Colors.END}")

    else:  # Okta SSO
        config.teleport.auth_method = "okta"
        config.teleport.proxy = proxy
        config.teleport.cluster = cluster

        cmd = [
            "tsh", "login",
            f"--proxy={proxy}",
            cluster,
            "--auth=okta"
        ]

        print(f"\n{Colors.YELLOW}This will open your browser for Okta authentication.{Colors.END}")

    success = run_command(cmd, "Logging in to Teleport")

    if success:
        print(f"\n{Colors.GREEN}✓ Teleport login successful{Colors.END}")
    else:
        print(f"\n{Colors.RED}✗ Teleport login failed{Colors.END}")

    return success


def setup_apollo(config: Config, status: AuthStatus) -> bool:
    """Guide user through Apollo CLI setup."""
    print_header("Apollo CLI Setup")

    # Check if already configured via env vars
    if os.environ.get("APOLLO_CLIENT") and os.environ.get("APOLLO_SECRET"):
        print(f"  {Colors.GREEN}✓{Colors.END} Apollo credentials found in environment variables")
        config.apollo.configured = True
        return True

    if status.apollo_configured:
        print("  Already configured")
        return True

    print("""
  Apollo CLI needs credentials to publish to the registry.

  You have two options:
    1. Set environment variables (recommended):
       export APOLLO_CLIENT="your-client-id"
       export APOLLO_SECRET="your-client-secret"

    2. Run: apollo-cli configure
""")

    choice = prompt_choice(
        "How would you like to configure Apollo?",
        [
            "I'll set environment variables myself",
            "Run apollo-cli configure now",
            "Skip for now"
        ],
        default=1
    )

    if choice == 1:
        print(f"""
  {Colors.YELLOW}Add these to your ~/.bashrc or ~/.zshrc:{Colors.END}

    export APOLLO_CLIENT="your-client-id"
    export APOLLO_SECRET="your-client-secret"

  Then restart your terminal or run: source ~/.bashrc
""")
        questionary.press_any_key_to_continue(
            "Press Enter when done...",
            style=custom_style
        ).ask()

        # Re-check
        if os.environ.get("APOLLO_CLIENT") and os.environ.get("APOLLO_SECRET"):
            config.apollo.configured = True
            return True
        else:
            print(f"  {Colors.YELLOW}Environment variables not detected. You may need to restart your terminal.{Colors.END}")
            config.apollo.configured = False
            return False

    elif choice == 2:
        success = run_command(["apollo-cli", "configure"], "Configuring Apollo CLI")
        config.apollo.configured = success
        return success

    else:
        print("  Skipping Apollo setup. Some features won't be available.")
        config.apollo.configured = False
        return False


def setup_aws(config: Config, status: AuthStatus) -> bool:
    """Check AWS setup."""
    print_header("AWS Setup (for Bedrock)")

    if status.aws_configured:
        print(f"  {Colors.GREEN}✓{Colors.END} AWS credentials configured")
        print(f"    Identity: {status.aws_identity}")
        return True

    print("""
  AWS credentials are needed to use Claude via Bedrock.

  Options:
    1. Run: aws configure
    2. Set up AWS SSO: aws sso login
    3. Use environment variables
""")

    choice = prompt_choice(
        "How would you like to configure AWS?",
        [
            "Run aws configure",
            "Run aws sso login",
            "I'll set it up myself",
            "Skip for now"
        ],
        default=3
    )

    if choice == 1:
        return run_command(["aws", "configure"], "Configuring AWS")
    elif choice == 2:
        return run_command(["aws", "sso", "login"], "AWS SSO Login")
    elif choice == 3:
        print("  Configure AWS credentials and restart the agent.")
        return False
    else:
        print("  Skipping AWS setup. The agent won't be able to use Bedrock.")
        return False


def print_summary(status: AuthStatus):
    """Print final status summary."""
    print_header("Setup Summary")

    print_status("Teleport", status.teleport_logged_in, status.teleport_user or "")
    print_status("Apollo CLI", status.apollo_configured)
    print_status("AWS (Bedrock)", status.aws_configured, status.aws_identity or "")

    if status.all_ready:
        print(f"\n{Colors.GREEN}{Colors.BOLD}✓ All set! You're ready to use the agent.{Colors.END}")
    else:
        print(f"\n{Colors.YELLOW}Some services need setup. Run 'esai-agent --setup' to continue.{Colors.END}")


def run_setup_wizard(force: bool = False) -> Config:
    """
    Run the full interactive setup wizard.

    This is the main entry point for guided setup.
    """
    print(f"""
{Colors.BOLD}╔═══════════════════════════════════════════════════════════╗
║           EdgescaleAI Agent Setup                           ║
╚═══════════════════════════════════════════════════════════╝{Colors.END}

This will help you configure access to:
  • Teleport (Cube cluster access)
  • Apollo CLI (Helm chart publishing)
  • AWS (Bedrock for Claude)

{Colors.YELLOW}Note: Your credentials are handled by native CLIs.
      We only store your preferences, never secrets.{Colors.END}
""")

    config = load_config()
    auth = AuthManager(config)
    status = auth.check_all()

    # Show current status
    print_header("Current Status")
    print_status("Teleport", status.teleport_logged_in, status.teleport_user or "")
    print_status("Apollo CLI", status.apollo_configured)
    print_status("AWS (Bedrock)", status.aws_configured, status.aws_identity or "")

    if status.all_ready and not force:
        print(f"\n{Colors.GREEN}Everything is configured!{Colors.END}")
        rerun = questionary.confirm(
            "Run setup anyway?",
            default=False,
            style=custom_style
        ).ask()
        if not rerun:
            return config

    # Run setup for each service
    setup_teleport(config, status)
    setup_apollo(config, status)
    setup_aws(config, status)

    # Save config and show final status
    config.setup_complete = True
    save_config(config)

    # Re-check status
    status = auth.check_all()
    print_summary(status)

    print(f"\n  Config saved to: ~/.esai/config.json")

    return config


def check_and_setup() -> tuple[Config, AuthStatus]:
    """
    Check auth status and run setup if needed.

    This is called before the agent starts.
    Returns (config, status).
    """
    config = load_config()
    auth = AuthManager(config)
    status = auth.check_all()

    if not status.all_ready:
        print(f"\n{Colors.YELLOW}Some services need authentication.{Colors.END}\n")

        choice = questionary.select(
            "What would you like to do?",
            choices=[
                "Run setup wizard",
                "Continue anyway (some features may not work)",
                "Exit"
            ],
            style=custom_style
        ).ask()

        if choice == "Run setup wizard":
            config = run_setup_wizard()
            status = auth.check_all()
        elif choice == "Exit":
            sys.exit(0)

    return config, status
