"""
Configuration management for Sharey
Supports both config.json and environment variables
"""
import os
import json
from typing import Dict, Any, Optional

class Config:
    """Configuration handler for Sharey"""
    
    def __init__(self, config_file: str = "config.json"):
        self.config_file = config_file
        self.config = self._load_config()
        
    def _load_config(self) -> Dict[str, Any]:
        """Load configuration from JSON file with environment variable fallbacks"""
        config = {}
        
        # Try to load from JSON file first
        if os.path.exists(self.config_file):
            try:
                with open(self.config_file, 'r') as f:
                    config = json.load(f)
                print(f"✅ Loaded configuration from {self.config_file}")
            except (json.JSONDecodeError, FileNotFoundError) as e:
                print(f"⚠️  Error loading {self.config_file}: {e}")
                print("Falling back to environment variables...")
        else:
            print(f"⚠️  {self.config_file} not found, using environment variables")
        
        # Set defaults and apply environment variable overrides
        config = self._apply_defaults_and_env(config)
        
        return config
    
    def _apply_defaults_and_env(self, config: Dict[str, Any]) -> Dict[str, Any]:
        """Apply default values and environment variable overrides"""
        
        # Storage Configuration
        storage_config = config.get('storage', {})
        storage_config['backend'] = storage_config.get('backend', os.getenv('STORAGE_BACKEND', 'b2'))
        storage_config['local_path'] = storage_config.get('local_path', os.getenv('STORAGE_LOCAL_PATH', 'storage'))
        config['storage'] = storage_config
        
        # B2 Configuration
        b2_config = config.get('b2', {})
        b2_config['application_key_id'] = (
            b2_config.get('application_key_id') or 
            os.getenv('B2_APPLICATION_KEY_ID', 'your_key_id_here')
        )
        b2_config['application_key'] = (
            b2_config.get('application_key') or 
            os.getenv('B2_APPLICATION_KEY', 'your_application_key_here')
        )
        b2_config['bucket_name'] = (
            b2_config.get('bucket_name') or 
            os.getenv('B2_BUCKET_NAME', 'your_bucket_name_here')
        )
        config['b2'] = b2_config
        
        # Flask Configuration
        flask_config = config.get('flask', {})
        flask_config['host'] = flask_config.get('host', os.getenv('FLASK_HOST', '127.0.0.1'))
        flask_config['port'] = int(flask_config.get('port', os.getenv('FLASK_PORT', 8866)))
        flask_config['debug'] = flask_config.get('debug', os.getenv('FLASK_DEBUG', 'true').lower() == 'true')
        config['flask'] = flask_config
        
        # Upload Configuration
        upload_config = config.get('upload', {})
        upload_config['max_file_size_mb'] = upload_config.get('max_file_size_mb', 100)
        config['upload'] = upload_config
        
        # Paste Configuration
        paste_config = config.get('paste', {})
        paste_config['max_length'] = paste_config.get('max_length', 1000000)
        config['paste'] = paste_config
        
        # Security Configuration
        security_config = config.get('security', {})
        security_config['rate_limit_enabled'] = security_config.get('rate_limit_enabled', False)
        security_config['max_uploads_per_hour'] = security_config.get('max_uploads_per_hour', 50)
        config['security'] = security_config
        
        return config
    
    def get(self, key: str, default: Any = None) -> Any:
        """Get configuration value using dot notation (e.g., 'b2.bucket_name')"""
        keys = key.split('.')
        value = self.config
        
        for k in keys:
            if isinstance(value, dict) and k in value:
                value = value[k]
            else:
                return default
        
        return value
    
    def validate_b2_config(self) -> bool:
        """Validate B2 configuration"""
        required_fields = ['application_key_id', 'application_key', 'bucket_name']
        invalid_values = ['your_key_id_here', 'your_application_key_here', 'your_bucket_name_here', '']
        
        for field in required_fields:
            value = self.get(f'b2.{field}')
            if not value or value in invalid_values:
                return False
        
        return True
    
    def validate_storage_config(self) -> bool:
        """Validate storage configuration"""
        backend = self.get('storage.backend', 'b2').lower()
        
        if backend == 'b2':
            return self.validate_b2_config()
        elif backend == 'local':
            # Local storage is always valid (will create directory if needed)
            return True
        else:
            print(f"❌ Unknown storage backend: {backend}")
            return False
    
    def get_storage_config(self) -> Dict[str, Any]:
        """Get storage configuration as dictionary"""
        return {
            'backend': self.get('storage.backend', 'b2'),
            'local_path': self.get('storage.local_path', 'storage')
        }
    
    def get_b2_config(self) -> Dict[str, str]:
        """Get B2 configuration as dictionary"""
        return {
            'key_id': self.get('b2.application_key_id'),
            'key': self.get('b2.application_key'),
            'bucket_name': self.get('b2.bucket_name')
        }
    
    def get_flask_config(self) -> Dict[str, Any]:
        """Get Flask configuration as dictionary"""
        return {
            'host': self.get('flask.host'),
            'port': self.get('flask.port'),
            'debug': self.get('flask.debug')
        }
    
    def save_config(self, config_dict: Dict[str, Any], backup: bool = True) -> bool:
        """Save configuration to JSON file"""
        try:
            # Create backup if requested
            if backup and os.path.exists(self.config_file):
                backup_file = f"{self.config_file}.backup"
                os.rename(self.config_file, backup_file)
                print(f"💾 Created backup: {backup_file}")
            
            # Save new configuration
            with open(self.config_file, 'w') as f:
                json.dump(config_dict, f, indent=2)
            
            print(f"✅ Configuration saved to {self.config_file}")
            return True
            
        except Exception as e:
            print(f"❌ Error saving configuration: {e}")
            return False
    
    def print_config(self, hide_secrets: bool = True) -> None:
        """Print current configuration"""
        print("\n📋 Current Configuration:")
        print("=" * 50)
        
        config_copy = json.loads(json.dumps(self.config))  # Deep copy
        
        if hide_secrets:
            # Hide sensitive information
            if 'b2' in config_copy:
                if 'application_key_id' in config_copy['b2']:
                    config_copy['b2']['application_key_id'] = '***HIDDEN***'
                if 'application_key' in config_copy['b2']:
                    config_copy['b2']['application_key'] = '***HIDDEN***'
        
        print(json.dumps(config_copy, indent=2))
        print("=" * 50)

# Global configuration instance
config = Config()
