"""
API Manager for Toxo Platform

This module provides dynamic API key management, allowing users to easily
configure their own Gemini API keys while providing sensible defaults.
"""

import os
from typing import Optional, Dict, Any
from pathlib import Path
import json
import yaml

from .config import ToxoConfig, GeminiConfig
from ..utils.logger import get_logger
from ..utils.exceptions import ConfigError


class ToxoAPIManager:
    """
    Manages API configurations for Toxo platform.
    
    Provides easy methods for users to configure their own API keys
    while maintaining fallback defaults and validation.
    """
    
    def __init__(self):
        """Initialize API manager."""
        self.logger = get_logger("toxo.api_manager")
        self.config_file = Path.home() / ".toxo" / "config.json"
        self.config_file.parent.mkdir(exist_ok=True)
        # No default fallback API key. Users must provide their own key.
        self.default_api_key = None
        
    def set_user_api_key(self, api_key: str, save_to_file: bool = True) -> bool:
        """
        Set user's API key.
        
        Args:
            api_key: User's Gemini API key
            save_to_file: Whether to save to user config file
            
        Returns:
            bool: True if key is valid and set successfully
        """
        try:
            # Validate API key format
            if not api_key or not api_key.startswith('AIza'):
                raise ConfigError("Invalid Gemini API key format. Key should start with 'AIza'.")
            
            # Set environment variable for current session
            os.environ["GEMINI_API_KEY"] = api_key
            
            # Save to user config file if requested
            if save_to_file:
                self._save_user_config({"gemini_api_key": api_key})
                
            self.logger.info("Successfully set user API key")
            return True
            
        except Exception as e:
            self.logger.error(f"Failed to set API key: {str(e)}")
            return False
    
    def get_api_key(self, prefer_user_key: bool = True) -> str:
        """
        Get the API key to use, following preference order.
        
        Args:
            prefer_user_key: Whether to prefer user-provided key over default
            
        Returns:
            str: API key to use
        """
        if prefer_user_key:
            # Priority order:
            # 1. Environment variable GEMINI_API_KEY
            # 2. Environment variable GOOGLE_API_KEY
            # 3. User config file
            # 4. No fallback key (users must provide their own)
            
            api_key = os.getenv("GEMINI_API_KEY")
            if api_key:
                return api_key
                
            api_key = os.getenv("GOOGLE_API_KEY") 
            if api_key:
                return api_key
                
            # Check user config file
            user_config = self._load_user_config()
            api_key = user_config.get("gemini_api_key")
            if api_key:
                return api_key
        
        raise ConfigError(
            "No Gemini API key configured. Set GEMINI_API_KEY/GOOGLE_API_KEY, "
            "or call set_user_api_key(...)."
        )
    
    def create_config(
        self, 
        api_key: Optional[str] = None,
        model: str = "gemini-2.5-flash-lite",
        temperature: float = 0.7,
        max_tokens: int = 8192,
        **kwargs
    ) -> ToxoConfig:
        """
        Create ToxoConfig with proper API key handling.
        
        Args:
            api_key: Optional API key (if None, will use get_api_key())
            model: Gemini model to use
            temperature: Generation temperature
            max_tokens: Maximum tokens
            **kwargs: Additional config parameters
            
        Returns:
            ToxoConfig: Configured Toxo configuration
        """
        # Use provided key or get from preference order
        final_api_key = api_key or self.get_api_key()
        
        gemini_config = GeminiConfig(
            api_key=final_api_key,
            model=model,
            temperature=temperature,
            max_tokens=max_tokens,
            test_mode=False
        )
        
        return ToxoConfig(gemini=gemini_config, **kwargs)
    
    def validate_api_key(self, api_key: str) -> bool:
        """
        Validate an API key by testing it.
        
        Args:
            api_key: API key to validate
            
        Returns:
            bool: True if key is valid
        """
        try:
            from ..integrations.gemini_client import GeminiClient
            
            # Create test config
            test_config = GeminiConfig(api_key=api_key, test_mode=False)
            client = GeminiClient(test_config)
            
            # Try to use the client (this will fail if key is invalid)
            # We'll implement a simple test method
            return client.test_connection()
            
        except Exception as e:
            self.logger.warning(f"API key validation failed: {str(e)}")
            return False
    
    def setup_interactive(self) -> ToxoConfig:
        """
        Interactive setup for new users.
        
        Returns:
            ToxoConfig: Configured Toxo configuration
        """
        print("🚀 Toxo Platform Setup")
        print("=" * 40)
        print("Let's configure your Gemini API key!")
        print()
        
        print("\nPlease provide your Gemini API key:")
        print("(Get one at: https://aistudio.google.com/app/apikey)")
        print()
        
        while True:
            api_key = input("Enter your Gemini API key: ").strip()
            
            if not api_key:
                print("❌ API key cannot be empty. Please try again.")
                continue
                
            if not api_key.startswith('AIza'):
                print("❌ Invalid key format. Gemini keys start with 'AIza'. Please try again.")
                continue
                
            print("🔍 Validating API key...")
            if self.validate_api_key(api_key):
                print("✅ API key is valid!")
                
                # Ask if user wants to save
                save = input("Save this key for future use? (y/n): ").lower().strip() == 'y'
                if save:
                    self.set_user_api_key(api_key, save_to_file=True)
                    print("✅ API key saved to user config")
                break
            else:
                print("❌ API key validation failed. Please check your key and try again.")
        
        # Create configuration
        config = self.create_config(api_key=api_key)
        
        print("\n🎉 Setup complete!")
        print("Ready to use Toxo platform!")
        
        return config
    
    def _save_user_config(self, config_data: Dict[str, Any]) -> None:
        """Save user configuration to file."""
        try:
            existing_config = {}
            if self.config_file.exists():
                with open(self.config_file, 'r') as f:
                    existing_config = json.load(f)
            
            # Update with new data
            existing_config.update(config_data)
            
            with open(self.config_file, 'w') as f:
                json.dump(existing_config, f, indent=2)
                
        except Exception as e:
            self.logger.warning(f"Failed to save user config: {str(e)}")
    
    def _load_user_config(self) -> Dict[str, Any]:
        """Load user configuration from file."""
        try:
            if self.config_file.exists():
                with open(self.config_file, 'r') as f:
                    return json.load(f)
        except Exception as e:
            self.logger.warning(f"Failed to load user config: {str(e)}")
        
        return {}
    
    def list_configured_keys(self) -> Dict[str, str]:
        """
        List all configured API keys and their sources.
        
        Returns:
            Dict mapping source to API key (masked)
        """
        keys = {}
        
        # Environment variables
        if os.getenv("GEMINI_API_KEY"):
            keys["GEMINI_API_KEY (env)"] = os.getenv("GEMINI_API_KEY")[:20] + "..."
            
        if os.getenv("GOOGLE_API_KEY"):
            keys["GOOGLE_API_KEY (env)"] = os.getenv("GOOGLE_API_KEY")[:20] + "..."
        
        # User config file
        user_config = self._load_user_config()
        if user_config.get("gemini_api_key"):
            keys["User config file"] = user_config["gemini_api_key"][:20] + "..."
        
        # No default fallback
        
        return keys
    
    def clear_user_config(self) -> bool:
        """
        Clear user's saved configuration.
        
        Returns:
            bool: True if cleared successfully
        """
        try:
            if self.config_file.exists():
                self.config_file.unlink()
            
            # Also clear environment variable
            if "GEMINI_API_KEY" in os.environ:
                del os.environ["GEMINI_API_KEY"]
                
            self.logger.info("User configuration cleared")
            return True
            
        except Exception as e:
            self.logger.error(f"Failed to clear user config: {str(e)}")
            return False


# Global API manager instance
api_manager = ToxoAPIManager()


def get_default_config() -> ToxoConfig:
    """
    Get default Toxo configuration with proper API key handling.
    
    Returns:
        ToxoConfig: Default configuration
    """
    return api_manager.create_config()


def set_api_key(api_key: str, save: bool = True) -> bool:
    """
    Convenience function to set user's API key.
    
    Args:
        api_key: User's Gemini API key
        save: Whether to save to user config
        
    Returns:
        bool: True if successful
    """
    return api_manager.set_user_api_key(api_key, save_to_file=save)


def interactive_setup() -> ToxoConfig:
    """
    Convenience function for interactive setup.
    
    Returns:
        ToxoConfig: Configured Toxo configuration
    """
    return api_manager.setup_interactive() 