"""Init command for Flow SDK configuration.

Supports both interactive wizard and direct configuration via flags.

Examples:
    Interactive setup:
        $ flow init

    Direct configuration:
        $ flow init --provider fcp --api-key fkey_xxx --project myproject

    Dry run to preview:
        $ flow init --provider fcp --dry-run
"""

import asyncio
import logging
import os
import time
import webbrowser
from dataclasses import dataclass
from enum import Enum
from pathlib import Path
from typing import Any, Dict, List, Optional

import click
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.prompt import Confirm, Prompt
from rich.table import Table

from flow import Flow
from flow._internal.io.http import HttpClient
from flow.errors import AuthenticationError, NetworkError

from .base import BaseCommand, console

logger = logging.getLogger(__name__)


class ConfigStatus(Enum):
    """Configuration item status."""

    CONFIGURED = "configured"
    MISSING = "missing"
    INVALID = "invalid"
    OPTIONAL = "optional"


@dataclass
class ConfigItem:
    """Configuration item with status and metadata."""

    name: str
    status: ConfigStatus
    value: Optional[Any] = None
    source: Optional[str] = None  # 'env', 'file', 'default'
    display_value: Optional[str] = None  # For display purposes


class AdaptiveSetupWizard:
    """Interactive setup wizard for Flow SDK configuration.
    
    Detects existing configuration and guides users through setup.
    Supports incremental configuration and validation.
    """

    def __init__(self):
        """Initialize the wizard with empty configuration."""
        self.config = {}  # New configuration values to save
        self.config_path = Path.home() / ".flow" / "config.yaml"
        self.existing_config = {}  # Current file configuration
        self.config_status = {}  # Status of each component

    def run(self) -> bool:
        """Run the setup wizard.

        Returns:
            True if setup completed successfully
        """
        self._show_welcome()

        # Analyze current configuration
        self._analyze_configuration()

        # Show configuration status
        if not self._show_configuration_status():
            return False

        # Check if fully configured
        if self._is_fully_configured():
            console.print("\n[green]✓ All required components are configured![/green]")

            # Ask what to do
            choices = [
                "1. Verify configuration and exit",
                "2. Reconfigure components",
                "3. Configure optional components",
                "4. Exit without verification",
            ]

            console.print("\n[bold]What would you like to do?[/bold]")
            for choice in choices:
                console.print(f"  {choice}")

            action = Prompt.ask("\nSelect option", choices=["1", "2", "3", "4"], default="1")

            if action == "1":
                if self._verify_configuration():
                    console.print("\n[green]✓ Configuration verified successfully![/green]")
                    self._show_quick_start()
                    return True
                else:
                    console.print(
                        "\n[yellow]Configuration verification failed. Please reconfigure.[/yellow]"
                    )
                    if not self._configure_missing_items():
                        return False
            elif action == "2" or action == "3":
                if not self._configure_missing_items():
                    return False
            else:  # action == "4"
                console.print("\n[dim]Exiting without verification.[/dim]")
                return True
        else:
            # Not fully configured - go to configuration menu
            if not self._configure_missing_items():
                return False

        # Save configuration
        if not self._save_configuration():
            return False

        # Final verification
        if self._verify_configuration():
            self._show_completion()
            return True
        else:
            console.print(
                "\n[yellow]Setup completed but verification failed. Check your settings.[/yellow]"
            )
            return False

    def _show_welcome(self):
        """Display setup wizard welcome screen."""
        console.clear()
        console.print(
            Panel.fit(
                "[bold blue]Welcome to Flow SDK Setup[/bold blue]\n\n"
                "The simple way to run GPU workloads on Foundry Platform\n\n"
                "This wizard will help you:\n"
                "• Get and validate your API key\n"
                "• Select your project\n"
                "• Configure SSH access\n"
                "• Verify everything works",
                title="Flow SDK",
                border_style="blue",
            )
        )
        console.print()

    def _analyze_configuration(self):
        """Detect existing configuration from environment and files.
        
        Populates config_status with current state of all components.
        """
        # Load existing config file
        if self.config_path.exists():
            try:
                import yaml

                with open(self.config_path) as f:
                    self.existing_config = yaml.safe_load(f) or {}
            except Exception as e:
                logger.debug(f"Failed to load config: {e}")
                self.existing_config = {}

        # Check API Key - Required component
        api_key = os.environ.get("FCP_API_KEY") or self.existing_config.get("api_key")
        if api_key and not api_key.startswith("YOUR_"):
            self.config_status["api_key"] = ConfigItem(
                name="API Key",
                status=ConfigStatus.CONFIGURED,
                value=api_key,
                source="env" if "FCP_API_KEY" in os.environ else "file",
                display_value=self._get_api_key_display(api_key),
            )
        else:
            self.config_status["api_key"] = ConfigItem(name="API Key", status=ConfigStatus.MISSING)

        # Check Project - Required component
        project = os.environ.get("FCP_DEFAULT_PROJECT") or self.existing_config.get("project")
        if project and not project.startswith("YOUR_"):
            self.config_status["project"] = ConfigItem(
                name="Project",
                status=ConfigStatus.CONFIGURED,
                value=project,
                source="env" if "FCP_DEFAULT_PROJECT" in os.environ else "file",
                display_value=project,
            )
        else:
            self.config_status["project"] = ConfigItem(name="Project", status=ConfigStatus.MISSING)

        # Check SSH Keys - Optional component
        ssh_keys = os.environ.get("FCP_SSH_KEYS") or self.existing_config.get("default_ssh_key")
        if ssh_keys:
            self.config_status["ssh_keys"] = ConfigItem(
                name="SSH Keys",
                status=ConfigStatus.CONFIGURED,
                value=ssh_keys,
                source="env" if "FCP_SSH_KEYS" in os.environ else "file",
                display_value=self._get_ssh_key_display(ssh_keys),
            )
        else:
            self.config_status["ssh_keys"] = ConfigItem(
                name="SSH Keys",
                status=ConfigStatus.OPTIONAL,
                display_value="Not configured (optional)",
            )

        # Check Region - Optional component with default
        region = os.environ.get("FCP_DEFAULT_REGION") or self.existing_config.get("region")
        if region:
            self.config_status["region"] = ConfigItem(
                name="Region",
                status=ConfigStatus.CONFIGURED,
                value=region,
                source="env" if "FCP_DEFAULT_REGION" in os.environ else "file",
                display_value=region,
            )
        else:
            self.config_status["region"] = ConfigItem(
                name="Region", status=ConfigStatus.OPTIONAL, display_value="Default"
            )

    def _get_api_key_display(self, api_key: str) -> str:
        """Create safe display string for API key.

        Args:
            api_key: Full API key value

        Returns:
            Masked string showing only prefix and suffix (e.g., "fkey_1234...abcd")

        Example:
            >>> display = self._get_api_key_display("fkey_abcd1234efgh5678")
            >>> print(display)  # "fkey_abcd...5678"
        """
        if len(api_key) > 10:
            return f"{api_key[:8]}...{api_key[-4:]}"
        return "[CONFIGURED]"

    def _get_ssh_key_display(self, ssh_keys: str) -> str:
        """Create display string for SSH key configuration.

        Args:
            ssh_keys: SSH key ID(s), comma-separated for multiple

        Returns:
            Human-readable description of SSH key configuration

        Examples:
            >>> self._get_ssh_key_display("sshkey_abc123")
            'Platform key (sshkey_abc123...)'

            >>> self._get_ssh_key_display("sshkey_abc,sshkey_def")
            '2 keys configured'
        """
        if "," in ssh_keys:
            count = len(ssh_keys.split(","))
            return f"{count} keys configured"
        elif ssh_keys.startswith("sshkey_"):
            return f"Platform key ({ssh_keys[:14]}...)"
        else:
            return "Configured"

    def _show_configuration_status(self) -> bool:
        """Display current configuration status in a table.

        Returns:
            bool: Always True (kept for interface compatibility)

        Shows a table with:
        - Component name
        - Status (configured/missing/optional)
        - Current value (masked for sensitive data)
        - Source (env/file)
        """
        console.print("\n[bold]Configuration Status[/bold]")
        console.print("─" * 50)

        # Create status table
        table = Table(show_header=True, box=None)
        table.add_column("Component", style="bold")
        table.add_column("Status")
        table.add_column("Value")
        table.add_column("Source", style="dim")

        for item in self.config_status.values():
            status_style = {
                ConfigStatus.CONFIGURED: "[green]✓ Configured[/green]",
                ConfigStatus.MISSING: "[red]✗ Missing[/red]",
                ConfigStatus.INVALID: "[yellow]⚠ Invalid[/yellow]",
                ConfigStatus.OPTIONAL: "[dim]○ Optional[/dim]",
            }[item.status]

            table.add_row(item.name, status_style, item.display_value or "—", item.source or "—")

        console.print(table)
        return True

    def _is_fully_configured(self) -> bool:
        """Check if all required components are configured.

        Returns:
            bool: True if API key and project are both configured

        Note: Optional components (SSH keys, region) are not required
        for the SDK to function.
        """
        required = ["api_key", "project"]
        return all(
            self.config_status.get(name, ConfigItem(name, ConfigStatus.MISSING)).status
            == ConfigStatus.CONFIGURED
            for name in required
        )

    def _configure_missing_items(self) -> bool:
        """Present interactive menu for configuration.

        Returns:
            bool: True if user completed configuration (even partially)

        The menu dynamically updates based on configuration status:
        - Required missing items are highlighted
        - Configured items show current values
        - User can configure items in any order
        - Can exit at any time (with warning if required items missing)
        """
        # Check what's not configured
        missing_required = [
            (name, item)
            for name, item in self.config_status.items()
            if item.status == ConfigStatus.MISSING and name in ["api_key", "project"]
        ]

        missing_optional = [
            (name, item)
            for name, item in self.config_status.items()
            if item.status in [ConfigStatus.MISSING, ConfigStatus.OPTIONAL]
            and name not in ["api_key", "project"]
        ]

        if not missing_required and not missing_optional:
            return True

        # Interactive configuration loop
        while True:
            # Re-check what's not configured (status might have changed)
            missing_required = [
                (name, item)
                for name, item in self.config_status.items()
                if item.status == ConfigStatus.MISSING and name in ["api_key", "project"]
            ]

            missing_optional = [
                (name, item)
                for name, item in self.config_status.items()
                if item.status in [ConfigStatus.MISSING, ConfigStatus.OPTIONAL]
                and name not in ["api_key", "project"]
            ]

            # Show configuration menu
            console.print("\n[bold]Configuration Menu[/bold]")
            console.print("─" * 50)

            if missing_required:
                console.print("\n[yellow]Required components need configuration:[/yellow]")
                for name, item in missing_required:
                    console.print(f"  • {item.name}")

            if missing_optional:
                console.print("\n[dim]Optional components available:[/dim]")
                for name, item in missing_optional:
                    console.print(f"  • {item.name}")

            # Let user choose what to configure
            console.print("\n[bold]What would you like to do?[/bold]")

            choices = []
            choice_map = {}
            choice_num = 1

            # Add required items
            if self.config_status["api_key"].status != ConfigStatus.CONFIGURED:
                choices.append(f"{choice_num}. Configure API Key [REQUIRED]")
                choice_map[str(choice_num)] = "api_key"
                choice_num += 1
            else:
                choices.append(f"{choice_num}. Reconfigure API Key [✓ Configured]")
                choice_map[str(choice_num)] = "api_key"
                choice_num += 1

            if self.config_status["project"].status != ConfigStatus.CONFIGURED:
                choices.append(f"{choice_num}. Configure Project [REQUIRED]")
                choice_map[str(choice_num)] = "project"
                choice_num += 1
            else:
                choices.append(
                    f"{choice_num}. Change Project [✓ {self.config_status['project'].display_value}]"
                )
                choice_map[str(choice_num)] = "project"
                choice_num += 1

            # Add optional items
            if self.config_status["ssh_keys"].status != ConfigStatus.CONFIGURED:
                choices.append(f"{choice_num}. Configure SSH Keys [optional]")
                choice_map[str(choice_num)] = "ssh_keys"
                choice_num += 1
            else:
                choices.append(
                    f"{choice_num}. Manage SSH Keys [✓ {self.config_status['ssh_keys'].display_value}]"
                )
                choice_map[str(choice_num)] = "ssh_keys"
                choice_num += 1

            if self.config_status["region"].status != ConfigStatus.CONFIGURED:
                choices.append(f"{choice_num}. Configure Region [optional]")
                choice_map[str(choice_num)] = "region"
                choice_num += 1
            else:
                choices.append(
                    f"{choice_num}. Change Region [✓ {self.config_status['region'].display_value}]"
                )
                choice_map[str(choice_num)] = "region"
                choice_num += 1

            choices.append(f"{choice_num}. Advanced Settings")
            choice_map[str(choice_num)] = "advanced"
            choice_num += 1

            if missing_required:
                choices.append(f"{choice_num}. Configure all required items")
                choice_map[str(choice_num)] = "all_required"
                choice_num += 1

            choices.append("0. Done (save and exit)")

            for choice in choices:
                console.print(f"  {choice}")
            choice = Prompt.ask("\nSelect option", choices=list(choice_map.keys()) + ["0"])

            if choice == "0":
                # Check if required items are missing
                still_missing = [
                    item.name
                    for name, item in self.config_status.items()
                    if item.status == ConfigStatus.MISSING
                    and name in ["api_key", "project"]
                    and name not in self.config
                ]

                if still_missing:
                    console.print(
                        f"\n[yellow]Warning: Required items not configured: {', '.join(still_missing)}[/yellow]"
                    )
                    if not Confirm.ask("Exit anyway?", default=False):
                        continue

                return True

            action = choice_map.get(choice)

            if action == "api_key":
                console.print("\n[bold]Configuring API Key[/bold]")
                console.print("─" * 50)
                if self._setup_api_key():
                    # Update status immediately for menu display
                    self.config_status["api_key"].status = ConfigStatus.CONFIGURED
                    self.config_status["api_key"].value = self.config.get("api_key")
                    self.config_status["api_key"].display_value = self._get_api_key_display(
                        self.config["api_key"]
                    )

            elif action == "project":
                console.print("\n[bold]Configuring Project[/bold]")
                console.print("─" * 50)
                if self._setup_project():
                    self.config_status["project"].status = ConfigStatus.CONFIGURED
                    self.config_status["project"].value = self.config.get("project")
                    self.config_status["project"].display_value = self.config["project"]

            elif action == "ssh_keys":
                console.print("\n[bold]Configuring SSH Keys[/bold]")
                console.print("─" * 50)
                if self._setup_ssh_keys():
                    if "default_ssh_key" in self.config:
                        self.config_status["ssh_keys"].status = ConfigStatus.CONFIGURED
                        self.config_status["ssh_keys"].value = self.config["default_ssh_key"]
                        self.config_status["ssh_keys"].display_value = self._get_ssh_key_display(
                            self.config["default_ssh_key"]
                        )

            elif action == "region":
                console.print("\n[bold]Configuring Region[/bold]")
                console.print("─" * 50)
                region = Prompt.ask("Region", default="us-central1")
                self.config["region"] = region
                self.config_status["region"].status = ConfigStatus.CONFIGURED
                self.config_status["region"].value = region
                self.config_status["region"].display_value = region

            elif action == "advanced":
                self._setup_optional_settings()

            elif action == "all_required":
                # Configure all required items in sequence
                for name in ["api_key", "project"]:
                    if self.config_status[name].status != ConfigStatus.CONFIGURED:
                        console.print(f"\n[bold]Configuring {self.config_status[name].name}[/bold]")
                        console.print("─" * 50)

                        if (
                            name == "api_key"
                            and not self._setup_api_key()
                            or name == "project"
                            and not self._setup_project()
                        ):
                            return False

            # Show updated status after each change
            self._show_configuration_status()

    def _should_configure_ssh(self) -> bool:
        """Ask if user wants to configure SSH.

        Returns:
            bool: Always True (method kept for compatibility)

        Note: This method is deprecated in favor of the menu-driven approach
        but kept for backwards compatibility.
        """
        # This method is no longer needed with the new menu system
        return True

    def _setup_api_key(self) -> bool:
        """Configure and validate API key.

        Returns:
            True if valid API key was configured
        """
        # Check if already in environment
        env_key = os.environ.get("FCP_API_KEY")
        if env_key and not env_key.startswith("YOUR_"):
            console.print("[green]✓[/green] Found API key in environment")
            use_env = Confirm.ask("Use this API key?", default=True)
            if use_env:
                self.config["api_key"] = env_key
                return self._verify_api_key(env_key)

        console.print("\nFlow SDK requires an API key from MLFoundry.")
        console.print("\n[bold]Get your API key:[/bold]")
        console.print("1. Visit: [link]https://app.mlfoundry.com/account/apikeys[/link]")
        console.print("2. Sign in or create an account")
        console.print("3. Create a new key or copy an existing one")

        # Offer to open browser
        if Confirm.ask("\n[bold]Open browser?[/bold]", default=True):
            console.print("[dim]Opening browser...[/dim]")
            webbrowser.open("https://app.mlfoundry.com/account/apikeys")
            time.sleep(2)  # Give browser time to open

        # Get API key with validation
        console.print("\n[bold]Enter your API key[/bold]")
        console.print("[dim]Format: fkey_XXXXXXXXXXXXXXXXXXXXXXXX[/dim]")

        while True:
            api_key = Prompt.ask("\nAPI Key", password=True)

            if not api_key:
                console.print("[red]API key cannot be empty[/red]")
                continue

            # Validate format
            if not api_key.startswith("fkey_"):
                console.print("[yellow]WARNING: API keys typically start with 'fkey_'[/yellow]")
                if not Confirm.ask("Use this key anyway?", default=False):
                    continue

            # Verify the key works
            if self._verify_api_key(api_key):
                self.config["api_key"] = api_key
                return True
            else:
                if not Confirm.ask("\nTry a different key?", default=True):
                    return False

    def _verify_api_key(self, api_key: str) -> bool:
        """Verify API key validity.

        Args:
            api_key: API key to verify

        Returns:
            True if key is valid and API is reachable
        """
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            console=console,
        ) as progress:
            task = progress.add_task("Verifying API key...", total=None)

            try:
                client = HttpClient(
                    base_url=os.environ.get("FLOW_API_URL", "https://api.mlfoundry.com"),
                    headers={"Authorization": f"Bearer {api_key}"},
                )

                # Try to get projects list - this validates the API key
                response = client.request(
                    method="GET",
                    url="/v2/projects",
                )

                progress.update(task, description="[green]✓ API key verified![/green]")
                return True

            except AuthenticationError:
                progress.update(task, description="[red]✗ Invalid API key[/red]")
                console.print("\n[red]This API key is invalid or expired.[/red]")
                return False

            except NetworkError as e:
                progress.update(task, description="[red]✗ Network error[/red]")
                console.print(f"\n[red]Could not reach API:[/red] {e}")
                console.print("[dim]Check your internet connection and try again.[/dim]")
                return False

            except Exception as e:
                progress.update(task, description="[red]✗ Verification failed[/red]")
                console.print(f"\n[red]Error:[/red] {e}")
                return False

    def _setup_project(self) -> bool:
        """Configure project selection.

        Auto-discovers available projects from API when possible.
        
        Returns:
            True if project was configured
        """
        # Try to fetch projects from API
        projects = self._fetch_projects()

        if not projects:
            # Manual entry fallback
            console.print("\n[yellow]Could not fetch projects from API.[/yellow]")
            console.print("\nEnter your project name manually.")
            console.print(
                "[dim]To create projects: https://app.mlfoundry.com/settings/projects[/dim]"
            )

            project = Prompt.ask("\nProject name", default="default")
            if project:
                self.config["project"] = project
                return True
            return False

        # Single project - use automatically
        if len(projects) == 1:
            project = projects[0]["name"]
            console.print(f"\n[green]✓[/green] Using your project: [bold]{project}[/bold]")
            self.config["project"] = project
            return True

        # Multiple projects - let user choose
        console.print("\n[bold]Available projects:[/bold]")
        table = Table(show_header=True, box=None)
        table.add_column("#", style="dim")
        table.add_column("Project Name")
        table.add_column("Region", style="dim")

        for i, project in enumerate(projects, 1):
            table.add_row(str(i), project.get("name", "Unknown"), project.get("region", "—"))

        console.print(table)

        # Get selection with validation
        while True:
            choice = Prompt.ask("\nSelect project number", default="1")

            try:
                idx = int(choice) - 1
                if 0 <= idx < len(projects):
                    self.config["project"] = projects[idx]["name"]
                    return True
                else:
                    console.print("[red]Invalid selection[/red]")
            except ValueError:
                console.print("[red]Please enter a number[/red]")

    def _setup_ssh_keys(self) -> bool:
        """Configure SSH keys with platform integration.

        Returns:
            bool: True always (SSH is optional)

        SSH keys in Flow are platform-managed:
        1. Users upload public keys to MLFoundry web UI
        2. Platform assigns each key a unique ID (e.g., sshkey_ABC123)
        3. Flow config stores these IDs (not the keys themselves)
        4. Platform provisions keys on GPU instances automatically

        This method:
        - Explains the SSH key workflow clearly
        - Attempts to fetch existing platform keys
        - Helps users find local keys to upload
        - Guides through the upload process
        """
        console.print(
            """
SSH keys in Flow allow you to access your GPU instances via SSH.

[bold]Important:[/bold] Flow uses SSH keys managed in your MLFoundry account.
You need to upload your SSH public key to the platform first.

[bold]How it works:[/bold]
1. Upload your public key at: https://app.mlfoundry.com/account/sshkeys
2. The platform assigns it an ID like 'sshkey_ABC123'
3. Use that ID in your Flow configuration
4. Flow automatically provisions this key on your instances

[dim]Note: SSH access is optional. You can configure this later if needed.[/dim]
        """
        )

        # Check for platform SSH keys (if API supports it)
        platform_keys = self._fetch_ssh_keys()

        if platform_keys:
            console.print(
                f"\n[green]✓[/green] Found {len(platform_keys)} SSH key(s) in your account:"
            )

            table = Table(show_header=True, box=None)
            table.add_column("#", style="dim")
            table.add_column("Key ID")
            table.add_column("Name")
            table.add_column("Fingerprint", style="dim")

            for i, key in enumerate(platform_keys, 1):
                table.add_row(
                    str(i),
                    key.get("id", "Unknown"),
                    key.get("name", "Unnamed"),
                    key.get("fingerprint", "—")[:20] + "..." if key.get("fingerprint") else "—",
                )

            console.print(table)

            # Select key(s)
            choice = Prompt.ask("\nSelect key number (or 'skip' to configure later)", default="1")

            if choice.lower() == "skip":
                return True

            try:
                idx = int(choice) - 1
                if 0 <= idx < len(platform_keys):
                    self.config["default_ssh_key"] = platform_keys[idx]["id"]
                    console.print(f"[green]✓[/green] Selected key: {platform_keys[idx]['id']}")
                    return True
            except ValueError:
                pass

        # No platform keys found - guide user through upload process
        console.print("\n[yellow]No SSH keys found in your MLFoundry account.[/yellow]")

        # Check for local keys to suggest
        local_keys = self._find_local_ssh_keys()
        if local_keys:
            console.print(f"\n[dim]Found {len(local_keys)} local SSH key(s):[/dim]")
            for key in local_keys[:3]:  # Show first 3
                console.print(f"  • {key.name}")

            console.print("\n[bold]To use these keys:[/bold]")
            console.print("1. Go to: https://app.mlfoundry.com/ssh-keys")
            console.print("2. Click 'Add SSH Key'")
            console.print(f"3. Upload your public key (e.g., {local_keys[0]})")
            console.print("4. Copy the assigned key ID")
        else:
            console.print("\n[bold]To generate a new SSH key:[/bold]")
            console.print("Run: [cyan]ssh-keygen -t ed25519 -f ~/.ssh/flow_key[/cyan]")
            console.print("Then upload ~/.ssh/flow_key.pub to MLFoundry")

        if Confirm.ask("\nOpen SSH key management page?", default=True):
            webbrowser.open("https://app.mlfoundry.com/ssh-keys")
            time.sleep(2)

        # Manual entry option
        key_id = Prompt.ask("\nEnter SSH key ID (or press Enter to skip)", default="")

        if key_id:
            # Validate format
            if not key_id.startswith("sshkey_"):
                console.print("[yellow]WARNING: SSH key IDs usually start with 'sshkey_'[/yellow]")
                if not Confirm.ask("Use this ID anyway?", default=False):
                    return True

            self.config["default_ssh_key"] = key_id

        return True

    def _fetch_projects(self) -> List[Dict[str, Any]]:
        """Fetch user's projects from API.

        Returns:
            List of project dicts or empty list on failure
        """
        try:
            client = HttpClient(
                base_url=os.environ.get("FLOW_API_URL", "https://api.mlfoundry.com"),
                headers={"Authorization": f"Bearer {self.config.get('api_key', '')}"},
            )

            response = client.request(
                method="GET",
                url="/v2/projects",
            )

            return response if isinstance(response, list) else []

        except Exception as e:
            logger.debug(f"Failed to fetch projects: {e}")
            return []

    def _fetch_ssh_keys(self) -> List[Dict[str, Any]]:
        """Fetch user's SSH keys from MLFoundry API.

        Returns:
            List of SSH key dicts with 'id', 'name', and 'fingerprint' keys.
            Empty list if API doesn't support this endpoint yet.

        Note: This endpoint may not be implemented yet. The method
        gracefully handles 404 or other errors by returning empty list.
        """
        try:
            client = HttpClient(
                base_url=os.environ.get("FLOW_API_URL", "https://api.mlfoundry.com"),
                headers={"Authorization": f"Bearer {self.config.get('api_key', '')}"},
            )

            # This endpoint might not exist yet
            response = client.request(
                method="GET",
                url="/v2/ssh-keys",
            )

            return response if isinstance(response, list) else []

        except Exception:
            # API might not support this endpoint yet
            return []

    def _find_local_ssh_keys(self) -> List[Path]:
        """Find SSH public keys in user's .ssh directory.

        Returns:
            List of Path objects for *.pub files in ~/.ssh/

        Used to help users identify which local keys they might
        want to upload to the platform.
        """
        ssh_dir = Path.home() / ".ssh"
        if not ssh_dir.exists():
            return []

        return list(ssh_dir.glob("*.pub"))

    def _setup_optional_settings(self):
        """Configure advanced/optional settings.

        Handles:
        - Region selection (if not already configured)
        - Custom API URL (for development or private deployments)

        These settings are truly optional - the SDK will work
        without them using sensible defaults.
        """
        console.print("\n[bold]Advanced Settings[/bold]")
        console.print("─" * 50)

        # Region configuration
        if self.config_status["region"].status != ConfigStatus.CONFIGURED:
            if Confirm.ask("\nSet default region?", default=False):
                region = Prompt.ask("Region", default="us-central1")
                self.config["region"] = region

        # Custom API URL (for advanced users)
        current_url = os.environ.get("FLOW_API_URL", "https://api.mlfoundry.com")
        if current_url != "https://api.mlfoundry.com":
            console.print(f"\n[dim]Current API URL: {current_url}[/dim]")

        if Confirm.ask("\nUse custom API URL?", default=False):
            url = Prompt.ask("API URL", default=current_url)
            self.config["api_url"] = url

    def _save_configuration(self) -> bool:
        """Save configuration to YAML file and create env script.

        Returns:
            bool: True if save successful

        Creates two files:
        1. ~/.flow/config.yaml - YAML configuration (mode 0600)
        2. ~/.flow/env.sh - Shell environment script (mode 0600)

        Merges new config with existing to preserve unchanged values.
        """
        console.print("\n[bold]Saving Configuration[/bold]")
        console.print("─" * 50)

        try:
            # Merge with existing config (preserving unchanged values)
            final_config = self.existing_config.copy()
            final_config.update(self.config)

            # Create directory with secure permissions
            self.config_path.parent.mkdir(parents=True, exist_ok=True)

            # Save YAML config
            import yaml

            with open(self.config_path, "w") as f:
                yaml.dump(final_config, f, default_flow_style=False)

            # Set secure permissions (owner read/write only)
            self.config_path.chmod(0o600)

            console.print(f"[green]✓[/green] Configuration saved to: {self.config_path}")

            # Create environment script
            self._create_env_script(final_config)

            return True

        except Exception as e:
            console.print(f"[red]Failed to save configuration:[/red] {e}")
            return False

    def _create_env_script(self, config: Dict[str, Any]):
        """Create shell script with environment variables.

        Args:
            config: Configuration dict to export as env vars

        Creates ~/.flow/env.sh that can be sourced to set environment
        variables. This provides an alternative to the YAML config file.

        Example output:
            #!/bin/bash
            # Flow SDK environment variables
            # Source this file: source ~/.flow/env.sh

            export FCP_API_KEY="fkey_..."
            export FLOW_DEFAULT_PROJECT="my-project"
            export FLOW_SSH_KEYS="sshkey_abc123"
        """
        env_script = self.config_path.parent / "env.sh"

        with open(env_script, "w") as f:
            f.write("#!/bin/bash\n")
            f.write("# Flow SDK environment variables\n")
            f.write("# Source this file: source ~/.flow/env.sh\n\n")

            # Export each config value as environment variable
            if "api_key" in config:
                f.write(f'export FCP_API_KEY="{config["api_key"]}"\n')
            if "project" in config:
                f.write(f'export FLOW_DEFAULT_PROJECT="{config["project"]}"\n')
            if "region" in config:
                f.write(f'export FLOW_DEFAULT_REGION="{config["region"]}"\n')
            if "default_ssh_key" in config:
                f.write(f'export FLOW_SSH_KEYS="{config["default_ssh_key"]}"\n')
            if "api_url" in config:
                f.write(f'export FLOW_API_URL="{config["api_url"]}"\n')

        # Set secure permissions
        env_script.chmod(0o600)
        console.print(f"[green]✓[/green] Environment script: {env_script}")

    def _verify_configuration(self) -> bool:
        """Test that configuration allows SDK initialization.

        Returns:
            bool: True if Flow client can be created and basic API call succeeds

        Creates a Flow client instance and makes a simple API call
        to verify the complete configuration works end-to-end.
        """
        console.print("\n[bold]Verifying Configuration[/bold]")
        console.print("─" * 50)

        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            console=console,
        ) as progress:
            task = progress.add_task("Testing configuration...", total=None)

            # Set environment from merged config for verification
            if "api_key" in self.config:
                os.environ["FCP_API_KEY"] = self.config["api_key"]
            if "project" in self.config:
                os.environ["FCP_PROJECT"] = self.config["project"]

            try:
                # Test creating Flow client and basic operation
                client = Flow()
                # Try listing tasks (should work even with empty list)
                client.list_tasks(limit=1)

                progress.update(task, description="[green]✓ Configuration verified![/green]")
                return True

            except AuthenticationError:
                progress.update(task, description="[red]✗ Authentication failed[/red]")
                console.print("\n[red]API key authentication failed.[/red]")
                console.print("Please check your API key is valid.")
                return False

            except Exception as e:
                progress.update(task, description="[yellow]Verification warning[/yellow]")
                console.print(f"\n[yellow]Warning:[/yellow] {e}")
                # Non-fatal errors (e.g., empty task list) are OK
                return True

    def _create_example_file(self):
        """Create a quick-start example file for the user.

        Generates a simple GPU test configuration file that users can
        immediately run after setup to verify their configuration works.
        """
        import yaml

        example_config = {
            "name": "hello-flow",
            "instance_type": "a100-80gb.sxm.1x",
            "region": self.config.get("region", "us-central1-a"),
            "max_price_per_hour": 5.0,
            "command": '''echo "Hello from Flow SDK!"
echo "Running on: $(hostname)"
echo "Date: $(date)"
echo "GPU Information:"
nvidia-smi
echo "Task completed successfully!"''',
        }

        filename = "hello-flow.yaml"

        # Check if file already exists
        if Path(filename).exists():
            if not Confirm.ask(
                f"\n[yellow]{filename} already exists. Overwrite?[/yellow]", default=False
            ):
                # Try alternative name
                filename = "hello-flow-example.yaml"
                if Path(filename).exists():
                    console.print("[yellow]Example file creation skipped (file exists)[/yellow]")
                    return

        try:
            with open(filename, "w") as f:
                yaml.dump(example_config, f, default_flow_style=False, sort_keys=False)

            console.print(f"\n[green]✓ Created example file:[/green] {filename}")
            console.print(f"[dim]Run it with:[/dim] [cyan]flow submit {filename}[/cyan]")
        except Exception as e:
            console.print(f"[yellow]Could not create example file: {e}[/yellow]")

    def _show_quick_start(self):
        """Display quick start commands for configured users.

        Shows the most common Flow commands to get users started quickly.
        Only shown when configuration is complete and verified.
        """
        console.print("\n[bold]Quick Start[/bold]")
        console.print("─" * 50)
        console.print(
            """
Submit a job:
  [cyan]flow submit examples/configs/basic.yaml[/cyan]

Check status:
  [cyan]flow status[/cyan]

View logs:
  [cyan]flow logs <task-id>[/cyan]

For more help:
  [cyan]flow --help[/cyan]
        """
        )

    def _show_completion(self):
        """Display setup completion message with next steps.

        Shown after successful first-time setup to guide new users
        on what to do next.
        """
        console.print("\n" + "─" * 50)

        # Offer to create example file
        if Confirm.ask(
            "\n[bold]Would you like to create a quick-start example file?[/bold]", default=True
        ):
            self._create_example_file()

        console.print(
            Panel.fit(
                "[bold green]Setup complete[/bold green]\n\n"
                "You're ready to run GPU workloads with Flow!\n\n"
                "[bold]Quick Start:[/bold]\n"
                "• Submit a job: [cyan]flow submit examples/configs/basic.yaml[/cyan]\n"
                "• Check status: [cyan]flow status[/cyan]\n"
                "• View logs: [cyan]flow logs <task-id>[/cyan]\n\n"
                "[bold]Next Steps:[/bold]\n"
                "• Explore the examples/configs/ directory\n"
                "• Try: [cyan]flow example gpu-test > my-first-task.yaml[/cyan]\n"
                "• Read the documentation",
                title="Success",
                border_style="green",
            )
        )


def run_setup_wizard():
    """Entry point for the Flow SDK setup wizard.

    Returns:
        bool: True if setup completed successfully, False otherwise

    This function:
    - Creates and runs the adaptive setup wizard
    - Handles keyboard interrupts gracefully
    - Logs any unexpected errors for debugging

    Example:
        >>> from flow.cli_init import run_setup_wizard
        >>> if run_setup_wizard():
        ...     print("Setup successful!")
        ... else:
        ...     print("Setup failed or was cancelled")
    """
    wizard = AdaptiveSetupWizard()
    try:
        return wizard.run()
    except KeyboardInterrupt:
        console.print("\n\n[yellow]Setup cancelled[/yellow]")
        return False
    except Exception as e:
        console.print(f"\n\n[red]Setup error:[/red] {e}")
        logger.exception("Setup wizard error")
        return False


class InitCommand(BaseCommand):
    """Init command implementation.
    
    Handles both interactive wizard mode and direct configuration
    via command-line options.
    """

    @property
    def name(self) -> str:
        return "init"

    @property
    def help(self) -> str:
        return "Configure Flow SDK"

    def get_command(self) -> click.Command:
        @click.command(name=self.name, help=self.help)
        @click.option("--provider", envvar="FLOW_PROVIDER", help="Provider to use (default: fcp)")
        @click.option("--api-key", envvar="FCP_API_KEY", help="API key for authentication")
        @click.option("--project", envvar="FCP_PROJECT", help="Project name (FCP only)")
        @click.option("--region", envvar="FCP_REGION", help="Default region (FCP only)")
        @click.option("--api-url", envvar="FCP_API_URL", help="API endpoint URL (FCP only)")
        @click.option("--dry-run", is_flag=True, help="Show configuration without saving")
        def init(
            provider: Optional[str],
            api_key: Optional[str],
            project: Optional[str],
            region: Optional[str],
            api_url: Optional[str],
            dry_run: bool,
        ):
            """Configure Flow SDK.
            
            Sets up provider selection and authentication credentials.
            """
            # Run async function
            asyncio.run(self._init_async(provider, api_key, project, region, api_url, dry_run))

        return init

    async def _init_async(
        self,
        provider: Optional[str],
        api_key: Optional[str],
        project: Optional[str],
        region: Optional[str],
        api_url: Optional[str],
        dry_run: bool,
    ):
        """Execute init command.
        
        Args:
            provider: Provider name (default: fcp)
            api_key: API key for authentication
            project: Project name
            region: Default region
            api_url: Custom API endpoint
            dry_run: Preview without saving
        """
        if provider or api_key or project or region or api_url or dry_run:
            # Non-interactive mode with provided options
            await self._configure_with_options(
                provider, api_key, project, region, api_url, dry_run
            )
        else:
            # Interactive mode - run the wizard
            success = run_setup_wizard()
            if not success:
                raise click.exceptions.Exit(1)

    async def _configure_with_options(
        self,
        provider: Optional[str],
        api_key: Optional[str],
        project: Optional[str],
        region: Optional[str],
        api_url: Optional[str],
        dry_run: bool,
    ):
        """Configure using command-line options.
        
        Prompts for missing required values if needed.
        Validates provider and saves configuration.
        """
        # Default to fcp provider
        provider = provider or "fcp"

        # Validate provider
        if provider not in ["fcp", "local"]:
            console.print(f"[red]Error:[/red] Unknown provider: {provider}")
            console.print("Supported providers: fcp, local")
            raise click.exceptions.Exit(1)

        # Build configuration
        config = {"provider": provider}

        if provider == "fcp":
            # FCP-specific configuration
            if api_key:
                config["api_key"] = api_key
            else:
                # Try to get from interactive input
                api_key = await self._prompt_for_value(
                    "API Key",
                    password=True,
                    default=os.environ.get("FCP_API_KEY")
                )
                if api_key:
                    config["api_key"] = api_key

            if project:
                config["project"] = project
            else:
                project = await self._prompt_for_value(
                    "Project",
                    default=os.environ.get("FCP_PROJECT", "default")
                )
                if project:
                    config["project"] = project

            if region:
                config["region"] = region
            else:
                region = await self._prompt_for_value(
                    "Region",
                    default=os.environ.get("FCP_REGION", "us-central1-a")
                )
                if region:
                    config["region"] = region

            if api_url:
                config["api_url"] = api_url

        if dry_run:
            # Show configuration without saving
            console.print("\n[bold]Configuration (dry run)[/bold]")
            console.print("─" * 50)
            console.print(f"Provider: {provider}")

            if provider == "fcp":
                if "api_key" in config:
                    masked_key = self._mask_api_key(config["api_key"])
                    console.print(f"API Key: {masked_key}")
                if "project" in config:
                    console.print(f"Project: {config['project']}")
                if "region" in config:
                    console.print(f"Region: {config['region']}")
                if "api_url" in config:
                    console.print(f"API URL: {config['api_url']}")
        else:
            # Save configuration
            config_path = Path.home() / ".flow" / "config.yaml"
            config_path.parent.mkdir(parents=True, exist_ok=True)

            import yaml
            with open(config_path, "w") as f:
                yaml.dump(config, f, default_flow_style=False)

            config_path.chmod(0o600)
            console.print(f"[green]✓[/green] Configuration saved to: {config_path}")

    async def _prompt_for_value(
        self,
        name: str,
        password: bool = False,
        default: Optional[str] = None
    ) -> Optional[str]:
        """Prompt user for configuration value.
        
        Args:
            name: Value name to prompt for
            password: Hide input for sensitive values
            default: Default value if none provided
            
        Returns:
            User input or None
        """
        return await asyncio.get_event_loop().run_in_executor(
            None,
            lambda: Prompt.ask(name, password=password, default=default)
        )

    def _mask_api_key(self, api_key: str) -> str:
        """Mask API key for safe display.
        
        Example:
            'fkey_abcd1234efgh5678' -> 'fkey_abc...5678'
        """
        if len(api_key) > 10:
            return f"{api_key[:8]}...{api_key[-4:]}"
        return "[CONFIGURED]"


# Export command instance
command = InitCommand()
