"""Encryption utilities for API keys and sensitive data."""

import base64
import os
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from typing import Optional
from src.core.config import get_config
from src.core.logger import get_logger

logger = get_logger(__name__)


class EncryptionManager:
    """Manages encryption and decryption of sensitive data."""
    
    def __init__(self):
        """Initialize encryption manager."""
        self.config = get_config()
        self._key = self._get_or_create_key()
        self.cipher = Fernet(self._key)
    
    def _get_or_create_key(self) -> bytes:
        """Get or create encryption key."""
        # Try to get key from keyring first
        try:
            import keyring
            key = keyring.get_password("crypto_trader", "encryption_key")
            if key:
                return key.encode()
        except Exception as e:
            logger.warning(f"Could not get key from keyring: {e}")
        
        # Generate key from user's password or system
        # For now, use a file-based approach (in production, use keyring)
        key_file = self.config.config_dir / ".encryption_key"
        
        if key_file.exists():
            with open(key_file, 'rb') as f:
                return f.read()
        
        # Generate new key
        key = Fernet.generate_key()
        try:
            key_file.parent.mkdir(parents=True, exist_ok=True)
            with open(key_file, 'wb') as f:
                f.write(key)
            # Restrict permissions after file is created
            key_file.chmod(0o600)
        except Exception as e:
            logger.error(f"Failed to create encryption key file: {e}")
            raise
        
        # Try to store in keyring
        try:
            import keyring
            keyring.set_password("crypto_trader", "encryption_key", key.decode())
        except Exception:
            pass  # Fallback to file if keyring unavailable
        
        return key
    
    def encrypt(self, data: str) -> str:
        """Encrypt sensitive data.
        
        Args:
            data: Plain text data to encrypt
            
        Returns:
            Encrypted data as base64 string
        """
        if not data:
            return ""
        encrypted = self.cipher.encrypt(data.encode())
        return base64.b64encode(encrypted).decode()
    
    def decrypt(self, encrypted_data: str) -> str:
        """Decrypt sensitive data.
        
        Args:
            encrypted_data: Base64 encoded encrypted data
            
        Returns:
            Decrypted plain text
        """
        if not encrypted_data:
            return ""
        try:
            decoded = base64.b64decode(encrypted_data.encode())
            decrypted = self.cipher.decrypt(decoded)
            return decrypted.decode()
        except Exception as e:
            logger.error(f"Decryption failed: {e}")
            raise ValueError("Failed to decrypt data") from e


# Global encryption manager
_encryption_manager: Optional[EncryptionManager] = None


def get_encryption_manager() -> EncryptionManager:
    """Get global encryption manager instance."""
    global _encryption_manager
    if _encryption_manager is None:
        _encryption_manager = EncryptionManager()
    return _encryption_manager

