"""API key management with read-only/trading modes and encryption."""

from typing import Optional, Dict
from sqlalchemy.orm import Session
from src.core.database import get_database, Exchange
from src.core.logger import get_logger
from .encryption import get_encryption_manager

logger = get_logger(__name__)


class APIKeyManager:
    """Manages API keys with encryption and permission modes."""
    
    def __init__(self):
        """Initialize API key manager."""
        self.db = get_database()
        self.encryption = get_encryption_manager()
    
    async def add_exchange(
        self,
        name: str,
        api_key: str,
        api_secret: str,
        read_only: bool = True,
        sandbox: bool = False
    ) -> Exchange:
        """Add exchange with encrypted API credentials."""
        from sqlalchemy import select
        async with self.db.get_session() as session:
            try:
                # Check if exchange already exists
                stmt = select(Exchange).where(Exchange.name == name)
                result = await session.execute(stmt)
                existing = result.scalar_one_or_none()
                
                if existing:
                    raise ValueError(f"Exchange {name} already exists")
                
                # Encrypt credentials
                encrypted_key = self.encryption.encrypt(api_key)
                encrypted_secret = self.encryption.encrypt(api_secret)
                
                # Create exchange record
                exchange = Exchange(
                    name=name,
                    api_key_encrypted=encrypted_key,
                    api_secret_encrypted=encrypted_secret,
                    read_only=read_only,
                    sandbox=sandbox,
                    enabled=True
                )
                
                session.add(exchange)
                await session.commit()
                
                logger.info(f"Added exchange {name} (read_only={read_only}, sandbox={sandbox})")
                return exchange
            except Exception as e:
                await session.rollback()
                logger.error(f"Failed to add exchange {name}: {e}")
                raise
    
    async def get_exchange_credentials(self, exchange_id: int) -> Dict[str, str]:
        """Get decrypted exchange credentials."""
        from sqlalchemy import select
        async with self.db.get_session() as session:
            exchange = await session.get(Exchange, exchange_id)
            if not exchange:
                raise ValueError(f"Exchange {exchange_id} not found")
            
            if not exchange.api_key_encrypted or not exchange.api_secret_encrypted:
                # Return empty credentials for public data exchanges
                return {
                    "api_key": "",
                    "api_secret": "",
                    "read_only": getattr(exchange, 'read_only', True),
                    "sandbox": getattr(exchange, 'sandbox', False),
                }
            
            return {
                "api_key": self.encryption.decrypt(exchange.api_key_encrypted),
                "api_secret": self.encryption.decrypt(exchange.api_secret_encrypted),
                "read_only": exchange.read_only,
                "sandbox": exchange.sandbox,
            }
    
    async def update_exchange(
        self,
        exchange_id: int,
        api_key: Optional[str] = None,
        api_secret: Optional[str] = None,
        read_only: Optional[bool] = None,
        sandbox: Optional[bool] = None,
        enabled: Optional[bool] = None
    ) -> Exchange:
        """Update exchange configuration."""
        async with self.db.get_session() as session:
            try:
                exchange = await session.get(Exchange, exchange_id)
                if not exchange:
                    raise ValueError(f"Exchange {exchange_id} not found")
                
                if api_key is not None:
                    exchange.api_key_encrypted = self.encryption.encrypt(api_key)
                if api_secret is not None:
                    exchange.api_secret_encrypted = self.encryption.encrypt(api_secret)
                if read_only is not None:
                    exchange.read_only = read_only
                if sandbox is not None:
                    exchange.sandbox = sandbox
                if enabled is not None:
                    exchange.enabled = enabled
                
                await session.commit()
                logger.info(f"Updated exchange {exchange.name}")
                return exchange
            except Exception as e:
                await session.rollback()
                logger.error(f"Failed to update exchange {exchange_id}: {e}")
                raise
    
    async def delete_exchange(self, exchange_id: int):
        """Delete exchange and its credentials."""
        async with self.db.get_session() as session:
            try:
                exchange = await session.get(Exchange, exchange_id)
                if not exchange:
                    raise ValueError(f"Exchange {exchange_id} not found")
                
                await session.delete(exchange)
                await session.commit()
                logger.info(f"Deleted exchange {exchange.name}")
            except Exception as e:
                await session.rollback()
                logger.error(f"Failed to delete exchange {exchange_id}: {e}")
                raise
    
    async def list_exchanges(self) -> list[Exchange]:
        """List all exchanges."""
        from sqlalchemy import select
        async with self.db.get_session() as session:
            result = await session.execute(select(Exchange))
            return result.scalars().all()
    
    async def validate_permissions(self, exchange_id: int, requires_trading: bool = False) -> bool:
        """Validate if exchange has required permissions."""
        async with self.db.get_session() as session:
            exchange = await session.get(Exchange, exchange_id)
            if not exchange:
                return False
            
            if not exchange.enabled:
                return False
            
            if requires_trading and exchange.read_only:
                logger.warning(f"Exchange {exchange.name} is read-only but trading required")
                return False
            
            return True


# Global API key manager
_key_manager: Optional[APIKeyManager] = None


def get_key_manager() -> APIKeyManager:
    """Get global API key manager instance."""
    global _key_manager
    if _key_manager is None:
        _key_manager = APIKeyManager()
    return _key_manager

