"""Project initialization and creation commands for ConnectOnion CLI."""

import os
import re
import sys
import time
import shutil
import toml
import click
from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.table import Table
from rich.panel import Panel
from rich import box
from datetime import datetime
from pathlib import Path
from typing import Optional, Tuple, List

from ... import __version__
from ... import address

console = Console()


# ANSI color codes for better output
class Colors:
    HEADER = '\033[95m'
    BLUE = '\033[94m'
    CYAN = '\033[96m'
    GREEN = '\033[92m'
    YELLOW = '\033[93m'
    RED = '\033[91m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'
    END = '\033[0m'


def validate_project_name(name: str) -> Tuple[bool, str]:
    """Validate project name for common issues.
    
    Returns:
        Tuple of (is_valid, error_message)
    """
    if not name:
        return False, "Project name cannot be empty"
    
    if ' ' in name:
        return False, "Project name cannot contain spaces. Try using hyphens instead (e.g., 'my-agent')"
    
    if not re.match(r'^[a-zA-Z][a-zA-Z0-9-_]*$', name):
        return False, "Project name must start with a letter and contain only letters, numbers, hyphens, and underscores"
    
    if len(name) > 50:
        return False, "Project name is too long (max 50 characters)"
    
    return True, ""


def show_progress(message: str, duration: float = 0.5):
    """Show a brief progress spinner using Rich."""
    with Progress(
        SpinnerColumn(style="cyan"),
        TextColumn("[cyan]{task.description}"),
        transient=True,
        console=console,
    ) as progress:
        task_id = progress.add_task(message, total=None)
        end_time = time.time() + duration
        while time.time() < end_time:
            time.sleep(0.05)
        progress.remove_task(task_id)


class LoadingAnimation:
    """Context manager for showing loading animation during long operations."""
    
    def __init__(self, message: str):
        self.message = message
        self.progress = None
        self.task_id = None
        
    def __enter__(self):
        from rich.progress import Progress, SpinnerColumn, TextColumn
        self.progress = Progress(
            SpinnerColumn(style="cyan"),
            TextColumn("[cyan]{task.description}"),
            transient=False,
            console=console,
        )
        self.progress.start()
        self.task_id = self.progress.add_task(self.message, total=None)
        return self
        
    def update(self, new_message: str):
        """Update the loading message."""
        if self.progress and self.task_id is not None:
            self.progress.update(self.task_id, description=new_message)
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.progress:
            self.progress.stop()


def get_template_info() -> list:
    """Get template information for display."""
    return [
        ('minimal', '📦 Minimal', 'Basic agent structure'),
        ('playwright', '🎭 Playwright', 'Browser automation agent'),
        ('custom', '✨ Custom', 'AI-generated agent'),
    ]


def get_template_suggested_name(template: str) -> str:
    """Get suggested project name for a template."""
    suggestions = {
        'minimal': 'my-agent',
        'playwright': 'browser-agent',
        'custom': None  # Will be generated by AI
    }
    return suggestions.get(template, 'my-agent')


def api_key_setup_menu(temp_project_dir: Optional[Path] = None) -> Tuple[str, str, Path]:
    """Show API key setup options to the user.
    
    Args:
        temp_project_dir: Optional temporary project directory to use for auth
    
    Returns:
        Tuple of (api_key, provider, temp_dir) where temp_dir is the temporary project created for auth
    """
    from ... import address  # Import address module for key generation
    
    try:
        import questionary
        from questionary import Style
        
        custom_style = Style([
            ('question', 'fg:#00ffff bold'),
            ('pointer', 'fg:#00ff00 bold'),
            ('highlighted', 'fg:#00ff00 bold'),
            ('selected', 'fg:#00ffff'),
            ('separator', 'fg:#808080'),
            ('instruction', 'fg:#808080'),
        ])
        
        choices = [
            questionary.Choice(
                title="🔑 Enter my API key (OpenAI, Anthropic, Gemini)",
                value="own_key"
            ),
            questionary.Choice(
                title="⭐ Star for 100k free tokens",
                value="star"
            ),
            questionary.Choice(
                title="🧅 ConnectOnion credits (same price as OpenAI)",
                value="managed"
            ),
            questionary.Choice(
                title="⏭️  Skip (add to .env later)",
                value="skip"
            ),
        ]
        
        result = questionary.select(
            "How would you like to set up API access?",
            choices=choices,
            style=custom_style,
            instruction="(Use ↑/↓ arrows, press Enter to confirm)",
        ).ask()
        
        if result == "own_key":
            # Ask for their API key
            console.print("\n[cyan]Paste your API key (we'll detect the provider)[/cyan]")
            api_key = questionary.password("API key:").ask()
            if api_key:
                provider, key_type = detect_api_provider(api_key)
                console.print(f"[green]✓ {provider.title()} API key configured[/green]")
                return api_key, provider, None  # No temp dir for own keys
            return "", "", None
            
        elif result == "managed":
            # Use ConnectOnion managed keys - create temp project and authenticate
            import webbrowser
            import shutil
            from .auth_commands import do_auth_flow
            from pathlib import Path
            
            console.print("\n[cyan]🧅 ConnectOnion Managed Keys[/cyan]")
            console.print("• Same pricing as OpenAI/Anthropic")
            console.print("• No API key management needed")
            console.print("• Pay as you go with tokens")
            
            open_browser = questionary.confirm(
                "\nWould you like to open the purchase page?",
                default=True
            ).ask()
            
            if open_browser:
                console.print("\nOpening ConnectOnion in your browser...")
                webbrowser.open("https://o.openonion.ai")
            
            # Create temporary project directory
            temp_name = "connectonion-temp-project"
            temp_dir = Path(temp_name)
            counter = 1
            while temp_dir.exists():
                temp_dir = Path(f"{temp_name}-{counter}")
                counter += 1
            
            console.print(f"\n[yellow]Setting up temporary project for authentication...[/yellow]")
            temp_dir.mkdir(parents=True)
            
            # Create .co directory and generate keys
            co_dir = temp_dir / ".co"
            co_dir.mkdir()
            
            try:
                # Generate keys for this project
                addr_data = address.generate()
                address.save(addr_data, co_dir)
                
                # For managed keys, use the browser flow since they need to purchase
                console.print("\n[yellow]Authenticating with ConnectOnion...[/yellow]\n")
                
                # Use browser flow for purchase
                from .auth_commands import do_auth_flow
                if do_auth_flow(co_dir):
                    console.print("\n[green]✓ Authentication successful! You can now use ConnectOnion managed keys.[/green]")
                    return "managed", "connectonion", temp_dir  # Return the temp directory
                else:
                    # Auth failed, clean up
                    shutil.rmtree(temp_dir)
                    console.print("[yellow]Authentication failed. Please try again.[/yellow]")
                    return "", "", None
            except Exception as e:
                # Clean up on error
                if temp_dir.exists():
                    shutil.rmtree(temp_dir)
                console.print(f"[red]Error: {e}[/red]")
                return "", "", None
            
        elif result == "star":
            # Star for free credits - create temp project and authenticate immediately
            import webbrowser
            import shutil
            from .auth_commands import do_auth_flow
            from pathlib import Path
            
            console.print("\n[cyan]⭐ Get 100k Free Tokens[/cyan]")
            console.print("\nOpening GitHub in your browser...")
            
            # Try to open the GitHub repo for starring
            github_url = "https://github.com/wu-changxing/connectonion"
            try:
                webbrowser.open(github_url)
            except:
                pass  # Browser opening might fail in some environments
            
            # Keep asking until they confirm they've starred
            while True:
                already_starred = questionary.confirm(
                    "\nHave you starred our repository?",
                    default=False
                ).ask()
                
                if already_starred:
                    console.print("[green]✓ Thank you for your support![/green]")
                    
                    # Create temporary project directory
                    temp_name = "connectonion-temp-project"
                    temp_dir = Path(temp_name)
                    counter = 1
                    while temp_dir.exists():
                        temp_dir = Path(f"{temp_name}-{counter}")
                        counter += 1
                    
                    console.print(f"\n[yellow]Setting up temporary project for authentication...[/yellow]")
                    temp_dir.mkdir(parents=True)
                    
                    # Create .co directory and generate keys
                    co_dir = temp_dir / ".co"
                    co_dir.mkdir()
                    
                    try:
                        # Generate keys for this project
                        addr_data = address.generate()
                        address.save(addr_data, co_dir)
                        
                        # Run direct registration with the project keys (no browser)
                        console.print("\n[yellow]Activating your free credits...[/yellow]\n")
                        
                        from .auth_commands import do_direct_registration
                        if do_direct_registration(co_dir, registration_type="star"):
                            console.print("\n[green]✓ We verified your star. Thanks for supporting us![/green]")
                            console.print("[green]You now have 100k free tokens![/green]")
                            console.print("\n[cyan]You can use ConnectOnion models with the 'co/' prefix:[/cyan]")
                            console.print("  • co/o4-mini")
                            console.print("  • co/gpt-4o")
                            console.print("  • co/o4-mini")
                            console.print("  • co/gpt-5")
                            console.print("  • co/claude-3-haiku")
                            console.print("  • co/claude-3-sonnet")
                            
                            return "star", "connectonion", temp_dir  # Return the temp directory
                        else:
                            # Auth failed, clean up
                            shutil.rmtree(temp_dir)
                            console.print("[yellow]Authentication failed. Please try again.[/yellow]")
                            return "", "", None
                    except Exception as e:
                        # Clean up on error
                        if temp_dir.exists():
                            shutil.rmtree(temp_dir)
                        console.print(f"[red]Error: {e}[/red]")
                        return "", "", None
                    
                    break  # Exit the loop
                else:
                    console.print("\n[yellow]Please star the repository to get your free tokens![/yellow]")
                    console.print(f"\nIf the browser didn't open, visit: [cyan]{github_url}[/cyan]")
                    console.print("You can copy and paste this URL into your browser.")
                    console.print("\n[dim]We'll wait for you to star the repository...[/dim]")
                    # Loop will continue to ask again
            
            return "star", "connectonion", None  # Should not reach here
            
        elif result == "skip":
            # User chose to skip API setup
            console.print("\n[yellow]⏭️  Skipping API setup[/yellow]")
            console.print("[dim]You can add your API key later in the .env file[/dim]")
            return "skip", "", None  # Return "skip" as api_key to indicate skip choice
            
        else:
            raise KeyboardInterrupt()
            
    except ImportError:
        # Fallback to simple menu
        click.echo(f"\n{Colors.CYAN}🔑 API Key Setup{Colors.END}")
        click.echo("1. Enter my API key (OpenAI, Anthropic, Gemini)")
        click.echo("2. Star for 100k free tokens")
        click.echo("3. ConnectOnion credits (same price as OpenAI)")
        click.echo("4. Skip (add to .env later)")
        
        choice = click.prompt("Select option", type=click.IntRange(1, 4), default=1)
        
        if choice == 1:
            api_key = click.prompt("API key", default="", hide_input=True, show_default=False)
            if api_key:
                provider, key_type = detect_api_provider(api_key)
                click.echo(f"{Colors.GREEN}✓ {provider.title()} API key configured{Colors.END}")
                return api_key, provider, False  # No auth needed for own keys
            return "", "", False
        elif choice == 2:
            import webbrowser
            from .auth_commands import do_auth_flow
            
            click.echo(f"\n{Colors.CYAN}⭐ Get 100k Free Tokens{Colors.END}")
            click.echo("\nOpening GitHub in your browser...")
            
            # Try to open the GitHub repo for starring
            github_url = "https://github.com/wu-changxing/connectonion"
            try:
                webbrowser.open(github_url)
            except:
                pass  # Browser opening might fail in some environments
            
            # Keep asking until they confirm they've starred
            while True:
                already_starred = click.confirm("\nHave you starred our repository?", default=False)
                
                if already_starred:
                    click.echo(f"{Colors.GREEN}✓ Thank you for your support!{Colors.END}")
                    click.echo(f"\n{Colors.YELLOW}Authenticating to activate your free credits...{Colors.END}\n")
                    
                    try:
                        do_auth_flow()
                        click.echo(f"\n{Colors.GREEN}✓ We verified your star. Thanks for supporting us!{Colors.END}")
                        click.echo(f"{Colors.GREEN}You now have 100k free tokens!{Colors.END}")
                        click.echo(f"\n{Colors.CYAN}You can use ConnectOnion models with the 'co/' prefix:{Colors.END}")
                        click.echo("  • co/o4-mini")
                        click.echo("  • co/gpt-4o")
                        click.echo("  • co/o4-mini")
                        click.echo("  • co/gpt-5")
                        click.echo("  • co/claude-3-haiku")
                        click.echo("  • co/claude-3-sonnet")
                        break  # Success, exit the loop
                    except Exception as e:
                        click.echo(f"\n{Colors.RED}Authentication failed: {e}{Colors.END}")
                        click.echo(f"{Colors.YELLOW}Please try running: {Colors.BOLD}co auth{Colors.END}")
                        break  # Exit on auth failure
                else:
                    click.echo(f"\n{Colors.YELLOW}Please star the repository to get your free tokens!{Colors.END}")
                    click.echo(f"\nIf the browser didn't open, visit: {Colors.CYAN}{github_url}{Colors.END}")
                    click.echo("You can copy and paste this URL into your browser.")
                    click.echo(f"\n{Colors.DIM}We'll wait for you to star the repository...{Colors.END}")
                    # Loop will continue to ask again
            
            return "star", "connectonion", None
            
        elif choice == 3:
            # ConnectOnion managed keys
            import webbrowser
            
            click.echo(f"\n{Colors.CYAN}🧅 ConnectOnion Credits{Colors.END}")
            click.echo("• Same price as OpenAI")
            click.echo("• No API key management needed")
            click.echo("• Pay as you go with tokens")
            
            if click.confirm("\nWould you like to open the purchase page?", default=True):
                click.echo("\nOpening ConnectOnion in your browser...")
                webbrowser.open("https://o.openonion.ai")
            
            click.echo(f"\n{Colors.YELLOW}Authentication will happen after project setup{Colors.END}")
            
            return "managed", "connectonion", None
            
        elif choice == 4:
            # Skip
            click.echo(f"\n{Colors.YELLOW}⏭️  Skipping API setup{Colors.END}")
            click.echo(f"{Colors.DIM}You can add your API key later in the .env file{Colors.END}")
            return "skip", "", None
            
        else:
            return "", "", None


def interactive_menu(options: List[Tuple[str, str, str]], prompt: str = "Choose an option:") -> str:
    """Interactive menu with arrow key navigation using questionary.

    Args:
        options: List of (key, emoji+name, description) tuples
        prompt: Menu prompt text

    Returns:
        Selected option key
    """
    try:
        import questionary
        from questionary import Style
        
        # Custom style using questionary's styling
        custom_style = Style([
            ('question', 'fg:#00ffff bold'),
            ('pointer', 'fg:#00ff00 bold'),  # The > pointer
            ('highlighted', 'fg:#00ff00 bold'),  # Currently selected item
            ('selected', 'fg:#00ffff'),  # Selected item after pressing enter
            ('separator', 'fg:#808080'),
            ('instruction', 'fg:#808080'),  # (Use arrow keys)
        ])
        
        # Create choices with formatted strings
        choices = []
        for key, name, desc in options:
            # Format: "📦 Minimal - Basic agent"
            choice_text = f"{name} - {desc}"
            choices.append(questionary.Choice(title=choice_text, value=key))
        
        # Show the selection menu
        result = questionary.select(
            prompt,
            choices=choices,
            style=custom_style,
            instruction="(Use ↑/↓ arrows, press Enter to confirm)",
        ).ask()
        
        if result:
            # Find the selected option name for confirmation
            for key, name, _ in options:
                if key == result:
                    console.print(f"[green]✓ Selected:[/green] {name}")
                    break
            return result
        else:
            # User cancelled (pressed Ctrl+C or Escape)
            raise KeyboardInterrupt()
            
    except ImportError:
        # Fallback to the original Rich + Click implementation
        console.print()
        console.print(Panel.fit(prompt, style="cyan", border_style="cyan", title="Templates"))

        table = Table(box=box.SIMPLE_HEAVY)
        table.add_column("No.", justify="right", style="bold")
        table.add_column("Template", style="white")
        table.add_column("Description", style="dim")

        for i, (_, name, desc) in enumerate(options, 1):
            table.add_row(str(i), name, desc)

        console.print(table)

        selected = click.prompt(
            "Select [number]",
            type=click.Choice([str(i) for i in range(1, len(options) + 1)]),
            default='1',
            show_choices=False,
        )

        idx = int(selected) - 1
        selected_option = options[idx]
        console.print(f"[green]✓ Selected:[/green] {selected_option[1]}")
        return selected_option[0]


def get_template_preview(template: str) -> str:
    """Get a preview of what the template includes."""
    previews = {
        'minimal': """  📦 Minimal - Simple starting point
    ├── agent.py (50 lines) - Basic agent with example tool
    ├── .env - API key configuration
    ├── README.md - Quick start guide
    └── .co/ - Agent identity & metadata""",
        
        'web-research': """  🔍 Web Research - Data analysis & web scraping
    ├── agent.py (100+ lines) - Agent with web tools
    ├── tools/ - Web scraping & data extraction
    ├── .env - API key configuration
    ├── README.md - Usage examples
    └── .co/ - Agent identity & metadata""",
        
        'email-agent': """  📧 Email Agent - Professional email assistant
    ├── agent.py (400+ lines) - Full email management
    ├── README.md - Comprehensive guide
    ├── .env.example - Configuration options
    └── .co/ - Agent identity & metadata
    Features: inbox management, auto-respond, search, statistics""",
        
        'custom': """  ✨ Custom - AI generates based on your needs
    ├── agent.py - Tailored to your description
    ├── tools/ - Custom tools for your use case
    ├── .env - API key configuration
    ├── README.md - Custom documentation
    └── .co/ - Agent identity & metadata""",
        
        'meta-agent': """  🤖 Meta-Agent - ConnectOnion development assistant
    ├── agent.py - Advanced agent with llm_do
    ├── prompts/ - System prompts (4 files)
    ├── .env - API key configuration
    ├── README.md - Comprehensive guide
    └── .co/ - Agent identity & metadata""",
        
        'playwright': """  🎭 Playwright - Browser automation
    ├── agent.py - Browser control agent
    ├── prompt.md - System prompt
    ├── .env - API key configuration
    ├── README.md - Setup instructions
    └── .co/ - Agent identity & metadata"""
    }
    
    return previews.get(template, f"  📄 {template.title()} template")


def check_environment_for_api_keys() -> Optional[Tuple[str, str]]:
    """Check environment variables for API keys.
    
    Returns:
        Tuple of (provider, api_key) if found, None otherwise
    """
    import os
    
    # Check for various API key environment variables
    checks = [
        ('OPENAI_API_KEY', 'openai'),
        ('ANTHROPIC_API_KEY', 'anthropic'),
        ('GOOGLE_API_KEY', 'google'),
        ('GEMINI_API_KEY', 'google'),
        ('GROQ_API_KEY', 'groq'),
    ]
    
    for env_var, provider in checks:
        api_key = os.environ.get(env_var)
        if api_key and api_key != 'your-api-key-here' and not api_key.startswith('sk-your'):
            return provider, api_key
    
    return None


def detect_api_provider(api_key: str) -> Tuple[str, str]:
    """Detect API provider from key format.
    
    Returns:
        Tuple of (provider, key_type)
    """
    # Check Anthropic first (more specific prefix)
    if api_key.startswith('sk-ant-'):
        return 'anthropic', 'claude'
    
    # OpenAI formats
    if api_key.startswith('sk-proj-'):
        return 'openai', 'project'
    elif api_key.startswith('sk-'):
        return 'openai', 'user'
    
    # Google (Gemini)
    if api_key.startswith('AIza'):
        return 'google', 'gemini'
    
    # Groq
    if api_key.startswith('gsk_'):
        return 'groq', 'groq'
    
    # Default to OpenAI if unsure
    return 'openai', 'unknown'


def configure_env_for_provider(provider: str, api_key: str) -> str:
    """Generate .env content based on provider.
    
    Args:
        provider: API provider name
        api_key: The API key
        
    Returns:
        .env file content
    """
    configs = {
        'openai': {
            'var': 'OPENAI_API_KEY',
            'model': 'o4-mini'
        },
        'anthropic': {
            'var': 'ANTHROPIC_API_KEY', 
            'model': 'claude-3-haiku-20240307'
        },
        'google': {
            'var': 'GOOGLE_API_KEY',
            'model': 'gemini-pro'
        },
        'groq': {
            'var': 'GROQ_API_KEY',
            'model': 'llama3-70b-8192'
        },
        'connectonion': {
            'var': 'CONNECTONION_API_KEY',
            'model': 'co/o4-mini'  # Prefixed models for managed keys
        }
    }
    
    config = configs.get(provider, configs['openai'])
    
    # Special handling for ConnectOnion managed keys
    if provider == 'connectonion':
        if api_key == 'managed':
            return f"""# ConnectOnion Managed Keys Configuration
# Authenticate with: co auth
# Purchase credits at: https://o.openonion.ai
# Same pricing as OpenAI/Anthropic

# Model Configuration (use co/ prefix for managed models)
MODEL=co/o4-mini
# Available models: co/o4-mini, co/gpt-4o, co/claude-3-haiku, co/claude-3-sonnet

# No API key needed - authentication handled via JWT token from 'co auth'

# Optional: Override default settings
# MAX_TOKENS=2000
# TEMPERATURE=0.7
"""
        elif api_key == 'star':
            return f"""# ConnectOnion Free Credits (100k tokens)
# 1. Star us: https://github.com/wu-changxing/connectonion
# 2. Authenticate with: co auth
# 3. Your GitHub star will be verified automatically

# Model Configuration (use co/ prefix for managed models)
MODEL=co/o4-mini

# No API key needed - authentication handled via JWT token from 'co auth'

# Optional: Override default settings
# MAX_TOKENS=2000
# TEMPERATURE=0.7
"""
    
    return f"""# {provider.title()} API Configuration
{config['var']}={api_key}

# Model Configuration
MODEL={config['model']}

# Optional: Override default settings
# MAX_TOKENS=2000
# TEMPERATURE=0.7
"""


def generate_custom_template_with_name(description: str, api_key: str, model: str = None, loading_animation=None) -> Tuple[str, str]:
    """Generate custom agent template and suggested name using AI.
    
    Args:
        description: What the agent should do
        api_key: API key or token for LLM
        model: Optional model to use (e.g., "co/gpt-4o-mini")
        loading_animation: Optional LoadingAnimation instance to update
    
    Returns:
        Tuple of (agent_code, suggested_name)
    """
    import re
    
    # Default fallback values
    suggested_name = "custom-agent"
    
    # Try to use AI to generate name and code
    if model or api_key:
        try:
            from ...llm import create_llm
            
            # Use the model specified or default to gpt-4o-mini
            llm_model = model if model else "gpt-4o-mini"
            
            if loading_animation:
                loading_animation.update(f"Connecting to {llm_model}...")
            
            # Create LLM instance
            if model and model.startswith("co/"):
                # Using ConnectOnion managed keys - api_key is actually the JWT token
                llm = create_llm(model=llm_model, api_key=api_key)
            else:
                # Using user's API key
                llm = create_llm(model=llm_model, api_key=api_key if api_key else None)
            
            # Generate project name and code with AI
            prompt = f"""Based on this description: "{description}"
            
Generate:
1. A short, descriptive project name (lowercase, hyphenated, max 30 chars, no spaces)
2. Python code for a ConnectOnion agent that implements this functionality

Respond in this exact format:
PROJECT_NAME: your-suggested-name
CODE:
```python
# Your generated code here
```"""
            
            messages = [
                {"role": "system", "content": "You are an AI assistant that generates ConnectOnion agent code and project names."},
                {"role": "user", "content": prompt}
            ]
            
            if loading_animation:
                loading_animation.update(f"Generating agent code...")
            
            response = llm.complete(messages)
            
            if response.content:
                # Parse the response
                lines = response.content.split('\n')
                for line in lines:
                    if line.startswith("PROJECT_NAME:"):
                        suggested_name = line.replace("PROJECT_NAME:", "").strip()
                        # Validate name format
                        suggested_name = re.sub(r'[^a-z0-9-]', '', suggested_name.lower())
                        if len(suggested_name) > 30:
                            suggested_name = suggested_name[:30]
                        break
                
                # Extract code between ```python and ```
                if "```python" in response.content and "```" in response.content:
                    code_start = response.content.find("```python") + 9
                    code_end = response.content.find("```", code_start)
                    if code_end > code_start:
                        agent_code = response.content[code_start:code_end].strip()
                        return agent_code, suggested_name
                        
        except Exception as e:
            # If AI generation fails, fall back to simple generation
            print(f"AI generation failed: {e}, using fallback")
    
    # Fallback: Simple name generation from description
    words = description.lower().split()[:3]
    suggested_name = "-".join(re.sub(r'[^a-z0-9]', '', word) for word in words if word)
    if not suggested_name:
        suggested_name = "custom-agent"
    else:
        suggested_name = suggested_name + "-agent"
    
    if len(suggested_name) > 30:
        suggested_name = suggested_name[:30]
    
    # Fallback agent code
    agent_code = f"""# {description}
# Generated with ConnectOnion

from connectonion import Agent

def process_request(query: str) -> str:
    '''Process user queries for: {description}'''
    return f"Processing: {{query}}"

# Create agent
agent = Agent(
    name="{suggested_name.replace('-', '_')}",
    model="{'co/gpt-4o-mini' if model and model.startswith('co/') else 'gpt-4o-mini'}",
    system_prompt=\"\"\"You are an AI agent designed to: {description}
    
    Provide helpful, accurate, and concise responses.\"\"\",
    tools=[process_request]
)

if __name__ == "__main__":
    print(f"🤖 {suggested_name.replace('-', ' ').title()} Ready!")
    print("Type 'exit' to quit\\n")
    
    while True:
        user_input = input("You: ")
        if user_input.lower() in ['exit', 'quit']:
            break
        
        response = agent.input(user_input)
        print(f"Agent: {{response}}\\n")
"""
    
    return agent_code, suggested_name


def generate_custom_template(description: str, api_key: str) -> str:
    """Generate custom agent template using AI.
    
    This is a placeholder - actual implementation would call AI API.
    """
    # TODO: Implement actual AI generation
    return f"""# Custom Agent Generated from: {description}

from connectonion import Agent

def custom_tool(param: str) -> str:
    '''Custom tool for: {description}'''
    return f"Processing: {{param}}"

agent = Agent(
    name="custom_agent",
    system_prompt="You are a custom agent designed for: {description}",
    tools=[custom_tool]
)

if __name__ == "__main__":
    while True:
        user_input = input("You: ")
        if user_input.lower() == 'quit':
            break
        response = agent.input(user_input)
        print(f"Agent: {{response}}")
"""


def is_directory_empty(directory: str) -> bool:
    """Check if a directory is empty (ignoring .git directory)."""
    contents = os.listdir(directory)
    # Ignore '.', '..', and '.git' directory
    meaningful_contents = [item for item in contents if item not in ['.', '..', '.git']]
    return len(meaningful_contents) == 0


def is_special_directory(directory: str) -> bool:
    """Check if directory is a special system directory."""
    abs_path = os.path.abspath(directory)
    
    if abs_path == os.path.expanduser("~"):
        return True
    if abs_path == "/":
        return True
    if "/tmp" in abs_path or "temp" in abs_path.lower():
        return False
    
    system_dirs = ["/usr", "/etc", "/bin", "/sbin", "/lib", "/opt"]
    for sys_dir in system_dirs:
        if abs_path.startswith(sys_dir + "/") or abs_path == sys_dir:
            return True
    
    return False


def get_special_directory_warning(directory: str) -> str:
    """Get warning message for special directories."""
    abs_path = os.path.abspath(directory)
    
    if abs_path == os.path.expanduser("~"):
        return "⚠️  You're in your HOME directory. Consider creating a project folder first."
    elif abs_path == "/":
        return "⚠️  You're in the ROOT directory. This is not recommended!"
    elif any(abs_path.startswith(d) for d in ["/usr", "/etc", "/bin", "/sbin", "/lib", "/opt"]):
        return "⚠️  You're in a SYSTEM directory. This could affect system files!"
    
    return ""


def handle_init(ai: Optional[bool], key: Optional[str], template: Optional[str],
                description: Optional[str], yes: bool, force: bool):
    """Initialize a ConnectOnion project in the current directory."""
    from .auth_commands import do_auth_flow
    
    current_dir = os.getcwd()
    project_name = os.path.basename(current_dir) or "my-agent"
    
    # Header with color
    if not yes:
        click.echo(f"\n{Colors.CYAN}{Colors.BOLD}🧅 ConnectOnion Project Initializer{Colors.END}")
        click.echo(f"{Colors.CYAN}{'=' * 40}{Colors.END}")
        click.echo(f"\n📁 Initializing: {Colors.BOLD}{project_name}{Colors.END}")
        click.echo(f"📍 Location: {Colors.BOLD}{current_dir}{Colors.END}\n")
    
    # Check for special directories
    warning = get_special_directory_warning(current_dir)
    if warning:
        click.echo(f"{Colors.YELLOW}{warning}{Colors.END}")
        if not yes and not click.confirm(f"{Colors.YELLOW}Continue anyway?{Colors.END}"):
            click.echo(f"{Colors.YELLOW}Initialization cancelled.{Colors.END}")
            return
    
    # Check if directory is empty
    if not is_directory_empty(current_dir) and not force:
        existing_files = os.listdir(current_dir)[:5]
        click.echo(f"{Colors.YELLOW}⚠️  Directory not empty{Colors.END}")
        click.echo(f"{Colors.YELLOW}Existing files: {', '.join(existing_files[:5])}{Colors.END}")
        if not yes and not click.confirm(f"\n{Colors.YELLOW}Add ConnectOnion to existing project?{Colors.END}"):
            click.echo(f"{Colors.YELLOW}Initialization cancelled.{Colors.END}")
            return
    
    # AI setup
    provider = None
    if ai is None and not yes:
        # Check for environment API keys
        env_api = check_environment_for_api_keys()
        if env_api:
            provider, env_key = env_api
            click.echo(f"\n{Colors.GREEN}✓ Found {provider.title()} API key in environment{Colors.END}")
            ai = True
            if not key:
                key = env_key
        else:
            ai = click.confirm(f"\n{Colors.CYAN}Enable AI features?{Colors.END}", default=True)
    elif ai is None:
        ai = False
    
    # API key setup
    api_key = key
    if ai and not api_key and not yes:
        click.echo(f"\n{Colors.CYAN}🔑 API Key Setup{Colors.END}")
        click.echo("  Paste your API key (we'll detect the provider)")
        api_key = click.prompt("  API key", default="", hide_input=True, show_default=False)
        if api_key:
            provider, key_type = detect_api_provider(api_key)
            show_progress(f"Detecting provider... {provider.title()} ({key_type} key)")
            click.echo(f"  {Colors.GREEN}✓ {provider.title()} API key configured{Colors.END}")
    elif ai and api_key:
        provider, key_type = detect_api_provider(api_key)
    
    # Template selection
    if not template and not yes:
        # Check if directory has existing files
        has_existing_files = not is_directory_empty(current_dir)
        
        if has_existing_files:
            # For existing projects, offer option to just add ConnectOnion config
            template_info = [
                ('none', '⚙️  Just add ConnectOnion config', 'Add .co folder and .env without any template files'),
                ('minimal', '📦 Minimal', 'Basic agent structure'),
                ('playwright', '🎭 Playwright', 'Browser automation agent'),
            ]
            if ai:
                template_info.append(('custom', '✨ Custom', 'AI-generated agent'))
        else:
            # For empty directories, use normal template options
            template_info = get_template_info()
            # Filter out custom if AI is disabled
            if not ai:
                template_info = [t for t in template_info if t[0] != 'custom']
        
        template = interactive_menu(template_info, "Choose a template:")
    elif not template:
        # Default to 'none' for existing projects, 'minimal' for new
        template = 'none' if not is_directory_empty(current_dir) else 'minimal'
    
    # Handle custom template
    custom_code = None
    if template == 'custom':
        if not ai:
            click.echo(f"{Colors.RED}❌ Custom template requires AI to be enabled!{Colors.END}")
            return
        
        if not description and not yes:
            click.echo(f"\n{Colors.CYAN}🤖 Describe your agent:{Colors.END}")
            description = click.prompt("  What should your agent do?")
        elif not description:
            description = "A general purpose agent"
        
        show_progress("Generating custom template with AI...", 2.0)
        custom_code = generate_custom_template(description, api_key or "")
    
    # Start initialization
    show_progress("Initializing ConnectOnion project...", 1.0)
    
    # Get template directory
    cli_dir = Path(__file__).parent.parent
    template_dir = cli_dir / "templates" / template if template != 'none' else None
    
    if template_dir and not template_dir.exists() and template not in ['custom', 'none']:
        click.echo(f"{Colors.RED}❌ Template '{template}' not found!{Colors.END}")
        return
    
    # Copy template files
    files_created = []
    files_skipped = []
    
    if template not in ['custom', 'none'] and template_dir and template_dir.exists():
        for item in template_dir.iterdir():
            # Skip hidden files except .env.example
            if item.name.startswith('.') and item.name != '.env.example':
                continue
                
            dest_path = Path(current_dir) / item.name
            
            if item.is_dir():
                # Copy directory
                if dest_path.exists() and not force:
                    files_skipped.append(f"{item.name}/ (already exists)")
                else:
                    if dest_path.exists():
                        shutil.rmtree(dest_path)
                    shutil.copytree(item, dest_path)
                    files_created.append(f"{item.name}/")
            else:
                # Skip .env.example, we'll create .env directly
                if item.name == '.env.example':
                    continue
                # Copy file
                if dest_path.exists() and not force:
                    files_skipped.append(f"{item.name} (already exists)")
                else:
                    shutil.copy2(item, dest_path)
                    files_created.append(item.name)
    
    # Create custom agent.py if custom template
    if custom_code:
        agent_file = Path(current_dir) / "agent.py"
        agent_file.write_text(custom_code)
        files_created.append("agent.py")
    
    # Create .env file
    env_path = Path(current_dir) / ".env"
    if not env_path.exists() or force:
        if api_key and provider:
            env_content = configure_env_for_provider(provider, api_key)
        else:
            env_content = """# OpenAI API Key
OPENAI_API_KEY=sk-your-api-key-here

# Optional: Override default model
# MODEL=gpt-4o-mini
"""
        env_path.write_text(env_content)
        files_created.append(".env")
    else:
        files_skipped.append(".env (already exists)")
    
    # Create .co directory with metadata
    co_dir = Path(current_dir) / ".co"
    co_dir.mkdir(exist_ok=True)
    
    # Create docs directory and copy documentation
    docs_dir = co_dir / "docs"
    docs_dir.mkdir(exist_ok=True)
    
    # Copy ConnectOnion documentation - always include the master doc
    cli_dir = Path(__file__).parent.parent
    master_doc = cli_dir / "docs" / "co-vibecoding-principles-docs-contexts-all-in-one.md"
    if master_doc.exists():
        shutil.copy2(master_doc, docs_dir / "co-vibecoding-principles-docs-contexts-all-in-one.md")
        files_created.append(".co/docs/co-vibecoding-principles-docs-contexts-all-in-one.md")
    
    # Generate agent address
    try:
        # Try to load existing keys first
        existing_address = address.load(co_dir)
        if existing_address:
            addr_data = existing_address
        else:
            # Generate new keys
            addr_data = address.generate()
            # Save keys to .co/keys/
            address.save(addr_data, co_dir)
            files_created.append(".co/keys/")
    except ImportError:
        # If cryptography libraries not installed, generate placeholder
        addr_data = {
            "address": "0x" + "0" * 64,
            "short_address": "0x0000...0000",
            "email": "0x00000000@mail.openonion.ai"
        }
    
    # Create config.toml
    config = {
        "project": {
            "name": os.path.basename(current_dir) or "connectonion-agent",
            "created": datetime.now().isoformat(),
            "framework_version": __version__,
        },
        "cli": {
            "version": "1.0.0",
            "command": "co init",
            "template": template,
        },
        "agent": {
            "address": addr_data["address"],
            "short_address": addr_data["short_address"],
            "email": addr_data.get("email", f"{addr_data['address'][:10]}@mail.openonion.ai"),
            "email_active": addr_data.get("email_active", False),
            "created_at": datetime.now().isoformat(),
            "algorithm": "ed25519",
            "default_model": "gpt-4o-mini" if provider == 'openai' else "gpt-4o-mini",
            "max_iterations": 10,
        },
    }
    
    config_path = co_dir / "config.toml"
    with open(config_path, "w") as f:
        toml.dump(config, f)
    files_created.append(".co/config.toml")
    
    # Handle .gitignore if in git repo
    if (Path(current_dir) / ".git").exists():
        gitignore_path = Path(current_dir) / ".gitignore"
        gitignore_content = """
# ConnectOnion
.env
.co/keys/
.co/cache/
.co/logs/
.co/history/
*.py[cod]
__pycache__/
todo.md
"""
        if gitignore_path.exists():
            with open(gitignore_path, "a") as f:
                if "# ConnectOnion" not in gitignore_path.read_text():
                    f.write(gitignore_content)
            files_created.append(".gitignore (updated)")
        else:
            gitignore_path.write_text(gitignore_content.lstrip())
            files_created.append(".gitignore")
    
    # Success message
    click.echo(f"\n{Colors.GREEN}✅ ConnectOnion project initialized!{Colors.END}")
    
    click.echo(f"\n📁 Project: {Colors.BOLD}{project_name}{Colors.END}")
    if template == 'none':
        click.echo(f"⚙️  Configuration: {Colors.BOLD}ConnectOnion config added{Colors.END}")
    else:
        click.echo(f"📦 Template: {Colors.BOLD}{template.title()}{Colors.END}")
    
    if custom_code and description:
        click.echo(f"\n✨ {Colors.CYAN}Custom agent generated from:{Colors.END}")
        click.echo(f"   {description[:60]}...")
    
    # Show agent address and email
    if 'addr_data' in locals() and addr_data.get('short_address'):
        click.echo(f"\n🔑 Agent address: {Colors.CYAN}{addr_data['short_address']}{Colors.END}")
        if addr_data.get('email'):
            # Automatically activate email for the agent
            if not addr_data.get('email_active', False):
                # Silently activate email in the background
                from .auth_commands import do_direct_registration
                if do_direct_registration(co_dir, registration_type="email"):
                    # Email is now activated
                    addr_data['email_active'] = True
            
            # Show email status after activation attempt
            email_status = "" if addr_data.get('email_active', False) else " (inactive)"
            status_color = Colors.GREEN if addr_data.get('email_active', False) else Colors.YELLOW
            click.echo(f"📧 Agent email: {Colors.CYAN}{addr_data['email']}{Colors.END}{status_color}{email_status}{Colors.END}")
    
    if files_created:
        click.echo(f"\n{Colors.CYAN}📂 Files created:{Colors.END}")
        for file in files_created:
            if file == "agent.py":
                click.echo(f"  • {Colors.GREEN}{file}{Colors.END} - Main agent implementation")
            elif file == "prompts/":
                click.echo(f"  • {Colors.GREEN}{file}{Colors.END} - System prompts directory")
            elif file == ".env":
                click.echo(f"  • {Colors.GREEN}{file}{Colors.END} - Environment configuration (add your API key)")
            elif file == "README.md":
                click.echo(f"  • {Colors.GREEN}{file}{Colors.END} - Project documentation")
            elif file == ".co/":
                click.echo(f"  • {Colors.GREEN}{file}{Colors.END} - ConnectOnion metadata")
            elif file == ".co/keys/":
                click.echo(f"  • {Colors.GREEN}{file}{Colors.END} - Agent cryptographic keys")
            else:
                click.echo(f"  • {Colors.GREEN}{file}{Colors.END}")
    
    if files_skipped:
        click.echo(f"\n{Colors.YELLOW}⚠️  Skipped (already exist):{Colors.END}")
        for file in files_skipped:
            click.echo(f"  • {file}")
    
    # Show .env reminder based on API key setup
    click.echo("")
    if api_key and provider:
        if provider == "connectonion":
            click.echo(f"💡 {Colors.CYAN}Using ConnectOnion credits - add your own key to .env if needed{Colors.END}")
        else:
            click.echo(f"💡 {Colors.CYAN}API key saved to .env - edit anytime to change providers{Colors.END}")
    else:
        click.echo(f"💡 {Colors.YELLOW}Add your API key to .env file to enable AI features{Colors.END}")
    
    # Next steps with color coding
    click.echo(f"\n{Colors.CYAN}🚀 Next steps:{Colors.END}")
    click.echo(f"{Colors.CYAN}{'─' * 40}{Colors.END}")
    
    step = 1
    if not api_key:
        click.echo(f"\n{step}️⃣  Add your API key to .env:")
        click.echo(f"    Open {Colors.BOLD}.env{Colors.END} and replace 'sk-your-api-key-here'")
        step += 1
    
    click.echo(f"\n{step}️⃣  Install dependencies:")
    click.echo(f"    {Colors.BOLD}pip install python-dotenv{Colors.END}")
    step += 1
    
    if template == "playwright":
        click.echo(f"    {Colors.BOLD}pip install playwright{Colors.END}")
        click.echo(f"    {Colors.BOLD}playwright install{Colors.END}")
        step += 1
    
    click.echo(f"\n{step}️⃣  Run your agent:")
    click.echo(f"    {Colors.BOLD}python agent.py{Colors.END}")
    
    click.echo(f"\n{Colors.CYAN}📚 Resources:{Colors.END}")
    click.echo(f"   Documentation: {Colors.UNDERLINE}https://github.com/wu-changxing/connectonion{Colors.END}")
    click.echo(f"   Discord: {Colors.UNDERLINE}https://discord.gg/4xfD9k8AUF{Colors.END}")
    click.echo()


def handle_create(name: Optional[str], ai: Optional[bool], key: Optional[str], 
                  template: Optional[str], description: Optional[str], yes: bool):
    """Create a new ConnectOnion project in a new directory."""
    from .auth_commands import do_auth_flow
    import signal
    import sys
    
    # Track temp directory for cleanup
    temp_project_dir = None
    
    def cleanup_on_exit(signum=None, frame=None):
        """Clean up temp directory on exit."""
        if temp_project_dir and temp_project_dir.exists():
            try:
                if click.confirm(f"\n{Colors.YELLOW}Remove temporary project directory '{temp_project_dir}'?{Colors.END}", default=True):
                    import shutil
                    shutil.rmtree(temp_project_dir)
                    click.echo(f"{Colors.GREEN}✓ Temporary directory removed.{Colors.END}")
            except Exception:
                pass
        sys.exit(0)
    
    # Register signal handler for Ctrl+C
    signal.signal(signal.SIGINT, cleanup_on_exit)
    
    # Show header
    if not yes:
        click.echo(f"\n{Colors.CYAN}{Colors.BOLD}🧅 ConnectOnion Project Creator{Colors.END}")
        click.echo(f"{Colors.CYAN}{'=' * 40}{Colors.END}\n")
    
    # Template selection FIRST
    if not template and not yes:
        template_info = get_template_info()
        template = interactive_menu(template_info, "Choose a template:")
    elif not template:
        template = 'minimal'
    
    # ALL templates need AI to function (agents need LLMs!)
    provider = None
    api_key = key
    ai = True  # Always true - all agents need AI
    
    # Check for environment API keys first
    if not api_key and not yes:
        env_api = check_environment_for_api_keys()
        if env_api:
            provider, env_key = env_api
            click.echo(f"\n{Colors.GREEN}✓ Found {provider.title()} API key in environment{Colors.END}")
            if not api_key:
                api_key = env_key
    
    # API key setup (temp_project_dir already declared above for signal handler)
    if ai and not api_key and not yes:
        api_key, provider, temp_project_dir = api_key_setup_menu()
        if api_key == "skip":
            # User chose to skip
            api_key = None
            ai = False  # Disable AI features since no API key
        elif not api_key and not provider:
            # User cancelled (Ctrl+C or similar)
            click.echo(f"{Colors.YELLOW}API key setup cancelled.{Colors.END}")
            return
    elif ai and api_key:
        provider, key_type = detect_api_provider(api_key)
    
    # Handle custom template
    custom_code = None
    ai_suggested_name = None
    if template == 'custom':
        # Custom template requires AI
        if not ai or not api_key:
            click.echo(f"{Colors.RED}❌ Custom template requires an API key for AI generation{Colors.END}")
            click.echo(f"{Colors.YELLOW}Please run 'co create' again and provide an API key{Colors.END}")
            return
        if not description and not yes:
            click.echo(f"\n{Colors.CYAN}🤖 Describe your agent:{Colors.END}")
            description = click.prompt("  What should your agent do?")
        elif not description:
            description = "A general purpose agent"
        
        # Use loading animation for AI generation
        click.echo(f"\n{Colors.CYAN}🤖 AI is generating your custom agent...{Colors.END}")
        
        with LoadingAnimation("Preparing AI generation...") as loading:
            # Use ConnectOnion model if available (user just got 100k tokens!)
            if provider == "connectonion" and temp_project_dir:
                # Load the JWT token from the temp project
                config_path = temp_project_dir / ".co" / "config.toml"
                jwt_token = None
                if config_path.exists():
                    try:
                        config = toml.load(config_path)
                        jwt_token = config.get("auth", {}).get("token")
                    except:
                        pass
                
                model_to_use = "co/gpt-4o-mini"
                loading.update(f"Using {model_to_use} to analyze: {description[:40]}...")
                
                # Pass JWT token as api_key for co/ models
                custom_code, ai_suggested_name = generate_custom_template_with_name(
                    description, jwt_token, model=model_to_use, loading_animation=loading
                )
            else:
                # Use user's API key and model
                loading.update(f"Analyzing: {description[:40]}...")
                custom_code, ai_suggested_name = generate_custom_template_with_name(
                    description, api_key or "", model=None, loading_animation=loading
                )
        
        click.echo(f"{Colors.GREEN}✓ Generated custom agent code{Colors.END}")
        click.echo(f"{Colors.GREEN}✓ Suggested project name: {ai_suggested_name}{Colors.END}")
    
    # Get project name
    if not name and not yes:
        if template == 'custom':
            # For custom template, ask for project name using AI suggestion
            if ai_suggested_name:
                # Use arrow key navigation for name selection
                try:
                    import questionary
                    from questionary import Style
                    
                    custom_style = Style([
                        ('question', 'fg:#00ffff bold'),
                        ('pointer', 'fg:#00ff00 bold'),
                        ('highlighted', 'fg:#00ff00 bold'),
                        ('selected', 'fg:#00ffff'),
                    ])
                    
                    choices = [
                        questionary.Choice(
                            title=f"🤖 {ai_suggested_name} (AI suggested)",
                            value=ai_suggested_name
                        ),
                        questionary.Choice(
                            title="✏️  Type your own name",
                            value="custom"
                        )
                    ]
                    
                    result = questionary.select(
                        "\nChoose a project name:",
                        choices=choices,
                        style=custom_style,
                        instruction="(Use ↑/↓ arrows, press Enter to confirm)",
                        default=choices[0]  # Default to AI suggestion
                    ).ask()
                    
                    if result == "custom":
                        name = click.prompt(f"{Colors.CYAN}Project name{Colors.END}")
                    else:
                        name = result
                        
                    click.echo(f"{Colors.GREEN}✓ Project name:{Colors.END} {name}")
                    
                except ImportError:
                    # Fallback to numbered menu
                    click.echo(f"\n{Colors.CYAN}Choose a project name:{Colors.END}")
                    click.echo(f"  1. {Colors.GREEN}{ai_suggested_name}{Colors.END} (AI suggested)")
                    click.echo(f"  2. Type your own")
                    
                    choice = click.prompt("Select [1-2]", type=click.IntRange(1, 2), default=1)
                    
                    if choice == 1:
                        name = ai_suggested_name
                    else:
                        name = click.prompt(f"{Colors.CYAN}Project name{Colors.END}")
            else:
                # No AI suggestion, ask for name
                name = click.prompt(f"\n{Colors.CYAN}Project name{Colors.END}", default="custom-agent")
        else:
            # For non-custom templates, use template name directly
            name = f"{template}-agent"
            click.echo(f"\n{Colors.GREEN}✓ Using template name:{Colors.END} {name}")
        
        # Validate project name
        is_valid, error_msg = validate_project_name(name)
        while not is_valid:
            click.echo(f"{Colors.RED}❌ {error_msg}{Colors.END}")
            name = click.prompt(f"{Colors.CYAN}Project name{Colors.END}", default="my-agent")
            is_valid, error_msg = validate_project_name(name)
    elif not name:
        # Auto mode - use template name for non-custom, AI suggestion for custom
        if template != 'custom':
            name = f"{template}-agent"
        elif ai_suggested_name:
            # Use AI-suggested name for custom template
            name = ai_suggested_name
        else:
            name = "my-agent"
    else:
        # Validate provided name
        is_valid, error_msg = validate_project_name(name)
        if not is_valid:
            click.echo(f"{Colors.RED}❌ {error_msg}{Colors.END}")
            return
    
    # Handle temp directory or create new project directory
    project_dir = Path(name)
    
    if temp_project_dir:
        # We have a temp directory from authentication, rename it
        if project_dir.exists():
            click.echo(f"{Colors.RED}❌ Directory '{name}' already exists!{Colors.END}")
            # Clean up temp directory
            shutil.rmtree(temp_project_dir)
            return
        
        # Rename temp directory to final project name
        show_progress(f"Finalizing project '{name}'...", 1.0)
        temp_project_dir.rename(project_dir)
    else:
        # Normal flow - check if directory exists and create
        if project_dir.exists():
            click.echo(f"{Colors.RED}❌ Directory '{name}' already exists!{Colors.END}")
            return
        
        # Create project directory
        show_progress(f"Creating project '{name}'...", 1.0)
        project_dir.mkdir(parents=True, exist_ok=True)
    
    # Get template files
    cli_dir = Path(__file__).parent.parent
    template_dir = cli_dir / "templates" / template
    
    if not template_dir.exists() and template != 'custom':
        click.echo(f"{Colors.RED}❌ Template '{template}' not found!{Colors.END}")
        shutil.rmtree(project_dir)
        return
    
    # Copy template files
    files_created = []
    
    if template != 'custom' and template_dir.exists():
        for item in template_dir.iterdir():
            if item.name.startswith('.') and item.name != '.env.example':
                continue
            
            dest_path = project_dir / item.name
            
            if item.is_dir():
                shutil.copytree(item, dest_path)
                files_created.append(f"{item.name}/")
            else:
                if item.name != '.env.example':
                    shutil.copy2(item, dest_path)
                    files_created.append(item.name)
    
    # Create custom agent.py if custom template
    if custom_code:
        agent_file = project_dir / "agent.py"
        agent_file.write_text(custom_code)
        files_created.append("agent.py")
    
    # Create .co directory (skip if it already exists from temp project)
    co_dir = project_dir / ".co"
    if not co_dir.exists():
        co_dir.mkdir(exist_ok=True)
    
    # Create docs directory
    docs_dir = co_dir / "docs"
    docs_dir.mkdir(exist_ok=True)
    
    # Copy ConnectOnion documentation - always include the master doc
    cli_dir = Path(__file__).parent.parent
    master_doc = cli_dir / "docs" / "co-vibecoding-principles-docs-contexts-all-in-one.md"
    if master_doc.exists():
        shutil.copy2(master_doc, docs_dir / "co-vibecoding-principles-docs-contexts-all-in-one.md")
        files_created.append(".co/docs/co-vibecoding-principles-docs-contexts-all-in-one.md")
    
    # Generate agent keys (skip if already exists from temp project)
    try:
        if temp_project_dir:
            # Keys already exist from authentication, just load them
            addr_data = address.load(co_dir)
        else:
            # Generate new keys
            addr_data = address.generate()
            address.save(addr_data, co_dir)
        files_created.append(".co/keys/")
    except ImportError:
        addr_data = {
            "address": "0x" + "0" * 64,
            "short_address": "0x0000...0000",
            "email": "0x00000000@mail.openonion.ai"
        }
    
    # Create config.toml
    config = {
        "project": {
            "name": name,
            "created": datetime.now().isoformat(),
            "framework_version": __version__,
        },
        "cli": {
            "version": "1.0.0",
            "command": f"co create {name}",
            "template": template,
        },
        "agent": {
            "address": addr_data["address"],
            "short_address": addr_data["short_address"],
            "email": addr_data.get("email", f"{addr_data['address'][:10]}@mail.openonion.ai"),
            "email_active": addr_data.get("email_active", False),
            "created_at": datetime.now().isoformat(),
            "algorithm": "ed25519",
            "default_model": "gpt-4o-mini" if provider == 'openai' else "gpt-4o-mini",
            "max_iterations": 10,
        },
    }
    
    config_path = co_dir / "config.toml"
    with open(config_path, "w") as f:
        toml.dump(config, f)
    files_created.append(".co/config.toml")
    
    # Create .env file
    env_path = project_dir / ".env"
    if api_key and provider:
        env_content = configure_env_for_provider(provider, api_key)
    else:
        env_content = """# OpenAI API Key
OPENAI_API_KEY=sk-your-api-key-here

# Optional: Override default model
# MODEL=gpt-4o-mini
"""
    env_path.write_text(env_content)
    files_created.append(".env")
    
    # Create .gitignore if in git repo
    if (project_dir / ".git").exists() or (Path.cwd() / ".git").exists():
        gitignore_path = project_dir / ".gitignore"
        gitignore_content = """
# ConnectOnion
.env
.co/keys/
.co/cache/
.co/logs/
.co/history/
*.py[cod]
__pycache__/
todo.md
"""
        gitignore_path.write_text(gitignore_content.lstrip())
        files_created.append(".gitignore")
    
    # Success message
    click.echo(f"\n{Colors.GREEN}✅ Project created successfully!{Colors.END}")
    
    click.echo(f"\n📁 Created: {Colors.BOLD}{name}{Colors.END}")
    click.echo(f"📦 Template: {Colors.BOLD}{template.title()}{Colors.END}")
    
    if custom_code and description:
        click.echo(f"\n✨ {Colors.CYAN}Custom agent generated from:{Colors.END}")
        click.echo(f"   {description[:60]}...")
    
    # Show agent address and email
    if 'addr_data' in locals() and addr_data.get('short_address'):
        click.echo(f"\n🔑 Agent address: {Colors.CYAN}{addr_data['short_address']}{Colors.END}")
        if addr_data.get('email'):
            # Automatically activate email for the agent
            if not addr_data.get('email_active', False):
                # Silently activate email in the background
                from .auth_commands import do_direct_registration
                if do_direct_registration(co_dir, registration_type="email"):
                    # Email is now activated
                    addr_data['email_active'] = True
            
            # Show email status after activation attempt
            email_status = "" if addr_data.get('email_active', False) else " (inactive)"
            status_color = Colors.GREEN if addr_data.get('email_active', False) else Colors.YELLOW
            click.echo(f"📧 Agent email: {Colors.CYAN}{addr_data['email']}{Colors.END}{status_color}{email_status}{Colors.END}")
    
    # Show .env reminder based on API key setup
    click.echo("")
    if api_key and api_key != "skip":
        if provider == "connectonion":
            click.echo(f"💡 {Colors.CYAN}Using ConnectOnion credits - add your own key to .env if needed{Colors.END}")
        else:
            click.echo(f"💡 {Colors.CYAN}API key saved to .env - edit anytime to change providers{Colors.END}")
    else:
        click.echo(f"💡 {Colors.YELLOW}Add your API key to .env file to enable AI features{Colors.END}")
    
    # Next steps with color coding
    click.echo(f"\n{Colors.CYAN}🚀 Next steps:{Colors.END}")
    click.echo(f"{Colors.CYAN}{'─' * 40}{Colors.END}")
    
    click.echo(f"\n1️⃣  Enter project directory:")
    click.echo(f"    {Colors.BOLD}cd {name}{Colors.END}")
    
    step = 2
    if not api_key:
        click.echo(f"\n{step}️⃣  Add your API key to .env:")
        click.echo(f"    Open {Colors.BOLD}.env{Colors.END} and replace 'sk-your-api-key-here'")
        step += 1
    
    click.echo(f"\n{step}️⃣  Install dependencies:")
    click.echo(f"    {Colors.BOLD}pip install python-dotenv{Colors.END}")
    step += 1
    
    if template == "playwright":
        click.echo(f"    {Colors.BOLD}pip install playwright{Colors.END}")
        click.echo(f"    {Colors.BOLD}playwright install{Colors.END}")
        step += 1
    
    click.echo(f"\n{step}️⃣  Run your agent:")
    click.echo(f"    {Colors.BOLD}python agent.py{Colors.END}")
    
    click.echo(f"\n{Colors.CYAN}📚 Resources:{Colors.END}")
    click.echo(f"   Documentation: {Colors.UNDERLINE}https://github.com/wu-changxing/connectonion{Colors.END}")
    click.echo(f"   Discord: {Colors.UNDERLINE}https://discord.gg/4xfD9k8AUF{Colors.END}")
    click.echo()
