"""Exchange factory for creating exchange adapters."""

from typing import Optional, Dict, Type, List
from src.core.database import get_database, Exchange
from src.core.logger import get_logger
from src.security.key_manager import get_key_manager
from .base import BaseExchangeAdapter

logger = get_logger(__name__)


class ExchangeFactory:
    """Factory for creating exchange adapter instances."""
    
    _adapters: Dict[str, Type[BaseExchangeAdapter]] = {}
    
    @classmethod
    def register(cls, name: str, adapter_class: Type[BaseExchangeAdapter]):
        """Register an exchange adapter.
        
        Args:
            name: Exchange name
            adapter_class: Adapter class
        """
        cls._adapters[name.lower()] = adapter_class
        logger.info(f"Registered exchange adapter: {name}")
    
    @classmethod
    async def create(cls, exchange_id: int) -> Optional[BaseExchangeAdapter]:
        """Create exchange adapter from database.
        
        Args:
            exchange_id: Exchange ID from database
            
        Returns:
            Exchange adapter instance or None
        """
        from sqlalchemy import select
        db = get_database()
        key_manager = get_key_manager()
        
        async with db.get_session() as session:
            try:
                stmt = select(Exchange).where(Exchange.id == exchange_id)
                result = await session.execute(stmt)
                exchange = result.scalar_one_or_none()
                
                if not exchange:
                    logger.error(f"Exchange {exchange_id} not found")
                    return None
                
                if not exchange.enabled:
                    logger.warning(f"Exchange {exchange.name} is disabled")
                    return None
                
                # Get adapter class
                adapter_class = cls._adapters.get(exchange.name.lower())
                if not adapter_class:
                    logger.error(f"No adapter registered for exchange: {exchange.name}")
                    return None
                
                # Check if this is a public data adapter (doesn't need credentials)
                from .public_data import PublicDataAdapter
                is_public_data = adapter_class == PublicDataAdapter
                
                if is_public_data:
                    # Public data adapter doesn't need credentials
                    adapter = adapter_class(
                        api_key="",
                        api_secret="",
                        sandbox=False,
                        read_only=True
                    )
                else:
                    # Get credentials for regular exchanges
                    credentials = await key_manager.get_exchange_credentials(exchange_id)
                    if not credentials:
                        logger.error(f"No credentials found for exchange: {exchange.name}")
                        return None
                    
                    # Create adapter instance
                    adapter = adapter_class(
                        api_key=credentials['api_key'],
                        api_secret=credentials['api_secret'],
                        sandbox=credentials['sandbox'],
                        read_only=credentials['read_only']
                    )
                
                # Connect
                if await adapter.connect():
                    logger.info(f"Connected to {exchange.name}")
                    return adapter
                else:
                    logger.error(f"Failed to connect to {exchange.name}")
                    return None
                    
            except Exception as e:
                logger.error(f"Failed to create exchange adapter: {e}")
                return None
    
    @classmethod
    async def create_by_name(
        cls,
        name: str,
        api_key: str,
        api_secret: str,
        sandbox: bool = False,
        read_only: bool = True
    ) -> Optional[BaseExchangeAdapter]:
        """Create exchange adapter directly.
        
        Args:
            name: Exchange name
            api_key: API key
            api_secret: API secret
            sandbox: Use sandbox/testnet
            read_only: Read-only mode
            
        Returns:
            Exchange adapter instance or None
        """
        adapter_class = cls._adapters.get(name.lower())
        if not adapter_class:
            logger.error(f"No adapter registered for exchange: {name}")
            return None
        
        try:
            adapter = adapter_class(
                api_key=api_key,
                api_secret=api_secret,
                sandbox=sandbox,
                read_only=read_only
            )
            
            if await adapter.connect():
                return adapter
            else:
                logger.error(f"Failed to connect to {name}")
                return None
        except Exception as e:
            logger.error(f"Failed to create exchange adapter: {e}")
            return None
    
    @classmethod
    def list_available(cls) -> List[str]:
        """List available exchange adapters.
        
        Returns:
            List of exchange names
        """
        return list(cls._adapters.keys())


# Convenience function
async def get_exchange(exchange_id: int) -> Optional[BaseExchangeAdapter]:
    """Get exchange adapter by ID.
    
    Args:
        exchange_id: Exchange ID
        
    Returns:
        Exchange adapter instance or None
    """
    return await ExchangeFactory.create(exchange_id)

