"""Helper utilities for CLI testing."""

import os
import tempfile
import shutil
from pathlib import Path
from typing import Optional, Dict, Any


class TemporaryDirectory:
    """Context manager for creating temporary directories for testing."""
    
    def __init__(self, empty: bool = True, with_git: bool = False):
        """
        Initialize temporary directory.
        
        Args:
            empty: If True, create empty directory. If False, add some files.
            with_git: If True, create a .git directory to simulate git repo.
        """
        self.empty = empty
        self.with_git = with_git
        self.temp_dir = None
    
    def __enter__(self) -> str:
        """Create and return the temporary directory path."""
        self.temp_dir = tempfile.mkdtemp()
        
        if not self.empty:
            # Add some existing files
            self._create_existing_files()
        
        if self.with_git:
            # Create .git directory
            git_dir = os.path.join(self.temp_dir, ".git")
            os.makedirs(git_dir)
        
        return self.temp_dir
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """Clean up the temporary directory."""
        if self.temp_dir and os.path.exists(self.temp_dir):
            shutil.rmtree(self.temp_dir)
    
    def _create_existing_files(self):
        """Create some existing files to simulate non-empty directory."""
        files_to_create = {
            "existing_file.txt": "Some existing content",
            "README.md": "# Existing Project\n\nThis is an existing project.",
            "src/main.py": "# Existing Python code\nprint('Hello, World!')"
        }
        
        for file_path, content in files_to_create.items():
            full_path = os.path.join(self.temp_dir, file_path)
            os.makedirs(os.path.dirname(full_path), exist_ok=True)
            with open(full_path, "w") as f:
                f.write(content)


def is_directory_empty(directory: str) -> bool:
    """
    Check if a directory is empty (only . and .. allowed).
    
    Args:
        directory: Path to check
        
    Returns:
        True if directory is empty or only contains . and ..
    """
    try:
        contents = os.listdir(directory)
        # Filter out . and .. which are always present
        meaningful_contents = [item for item in contents if item not in ['.', '..']]
        return len(meaningful_contents) == 0
    except (OSError, FileNotFoundError):
        return True


def is_special_directory(directory: str) -> bool:
    """
    Check if directory is a special system directory that should warn user.
    
    Args:
        directory: Path to check
        
    Returns:
        True if directory requires special warning
    """
    abs_path = os.path.abspath(directory)
    
    # Home directory
    if abs_path == os.path.expanduser("~"):
        return True
    
    # Root directory
    if abs_path == "/":
        return True
    
    # System directories
    system_dirs = ["/usr", "/etc", "/var", "/bin", "/sbin", "/lib", "/opt"]
    for sys_dir in system_dirs:
        if abs_path.startswith(sys_dir):
            return True
    
    return False


def get_special_directory_warning(directory: str) -> Optional[str]:
    """
    Get appropriate warning message for special directories.
    
    Args:
        directory: Path to check
        
    Returns:
        Warning message if directory is special, None otherwise
    """
    abs_path = os.path.abspath(directory)
    
    if abs_path == os.path.expanduser("~"):
        return "⚠️  You're in your home directory. This will add ConnectOnion files to ~/"
    
    if abs_path == "/":
        return "⚠️  You're in the root directory! This is not recommended."
    
    system_dirs = ["/usr", "/etc", "/var", "/bin", "/sbin", "/lib", "/opt"]
    for sys_dir in system_dirs:
        if abs_path.startswith(sys_dir):
            return f"⚠️  You're in a system directory ({sys_dir}). This is not recommended."
    
    return None


def create_test_agent_content() -> str:
    """
    Get the content for a basic test agent.py file.
    
    Returns:
        Python code string for agent.py
    """
    return '''"""ConnectOnion Agent - Generated by co init"""

from connectonion import Agent


def hello(name: str) -> str:
    """Greet someone by name."""
    return f"Hello, {name}! Welcome to ConnectOnion."


def calculate(expression: str) -> str:
    """Perform basic mathematical calculations."""
    try:
        # Only allow safe mathematical operations
        allowed_chars = "0123456789+-*/(). "
        if all(c in allowed_chars for c in expression):
            result = eval(expression)
            return f"Calculation result: {result}"
        else:
            return "Error: Invalid characters in expression"
    except Exception as e:
        return f"Math error: {str(e)}"


def get_time() -> str:
    """Get the current time."""
    from datetime import datetime
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")


# Create your agent
agent = Agent(
    name="my_agent",
    system_prompt="You are a helpful assistant with access to basic tools.",
    tools=[hello, calculate, get_time]
)


if __name__ == "__main__":
    # Example usage
    print("🤖 ConnectOnion Agent initialized!")
    print("Available tools:", agent.list_tools())
    
    # Interactive example
    result = agent.input("Say hello to the world and tell me what time it is")
    print("\\nAgent response:", result)
'''


def create_test_env_content() -> str:
    """
    Get the content for .env.example file.
    
    Returns:
        Content string for .env.example
    """
    return """# ConnectOnion Environment Configuration
# Copy this file to .env and add your actual API keys

# OpenAI API Key (required for most agents)
OPENAI_API_KEY=your-api-key-here

# Optional: Anthropic API Key (if using Claude)
# ANTHROPIC_API_KEY=your-anthropic-key-here

# Optional: Custom model settings
# OPENAI_MODEL=gpt-4
# OPENAI_MAX_TOKENS=1000
"""


def create_test_gitignore_content() -> str:
    """
    Get the content to add to .gitignore for ConnectOnion projects.
    
    Returns:
        Content string to append to .gitignore
    """
    return """
# ConnectOnion
.env
.co/

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Virtual environments
venv/
env/
ENV/
"""


def verify_agent_file_syntax(file_path: str) -> bool:
    """
    Verify that an agent.py file has valid Python syntax.
    
    Args:
        file_path: Path to the agent.py file
        
    Returns:
        True if file has valid Python syntax
    """
    try:
        with open(file_path, "r") as f:
            content = f.read()
        compile(content, file_path, 'exec')
        return True
    except (SyntaxError, FileNotFoundError):
        return False


def verify_agent_file_content(file_path: str) -> Dict[str, bool]:
    """
    Verify that an agent.py file contains expected content.
    
    Args:
        file_path: Path to the agent.py file
        
    Returns:
        Dictionary of checks and their results
    """
    try:
        with open(file_path, "r") as f:
            content = f.read()
    except FileNotFoundError:
        return {"file_exists": False}
    
    checks = {
        "file_exists": True,
        "imports_connectonion": "from connectonion import Agent" in content,
        "has_tools": "def " in content and ":" in content,
        "creates_agent": "agent = Agent(" in content,
        "has_main_block": 'if __name__ == "__main__":' in content,
        "valid_syntax": verify_agent_file_syntax(file_path)
    }
    
    return checks