"""
Configuration system for Voltie OCPP UDP client
Loads settings from environment variables and .env file
"""
import logging
from typing import Optional
from pydantic import field_validator
from pydantic_settings import BaseSettings

logger = logging.getLogger(__name__)


class Config(BaseSettings):
    """Configuration settings for Voltie OCPP UDP client"""
    
    # UDP Server Configuration
    udp_host: str = "0.0.0.0"
    udp_port: int = 9000
    
    # Backend Configuration
    backend_url: str  # Required field
    
    # Driver Configuration
    driver: str = "file"
    
    # Logging Configuration
    log_level: str = "INFO"
    
    # Storage Configuration
    storage_backend: str = "memory"
    redis_host: str = "localhost"
    redis_port: int = 6379
    redis_db: int = 0
    
    # Admin API Configuration
    api_host: str = "0.0.0.0"
    api_port: int = 8000
    api_enabled: bool = True
    
    # Security Configuration
    secret_key: Optional[str] = None
    
    model_config = {
        "env_file": ".env",
        "env_file_encoding": "utf-8",
        "case_sensitive": False,
        "extra": "ignore",  # Ignore extra fields from .env file
    }
        
    @field_validator("udp_port", "redis_port", "api_port")
    @classmethod
    def validate_ports(cls, v):
        """Validate port numbers are in valid range"""
        if not 1 <= v <= 65535:
            raise ValueError(f"Port must be between 1 and 65535, got {v}")
        return v
        
    @field_validator("driver")
    @classmethod
    def validate_driver(cls, v):
        """Validate driver type"""
        valid_drivers = ["file", "console", "null", "default"]
        if v not in valid_drivers:
            raise ValueError(f"Driver must be one of {valid_drivers}, got '{v}'")
        return v
        
    @field_validator("log_level")
    @classmethod
    def validate_log_level(cls, v):
        """Validate log level"""
        valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
        v_upper = v.upper()
        if v_upper not in valid_levels:
            raise ValueError(f"Log level must be one of {valid_levels}, got '{v}'")
        return v_upper
        
    @field_validator("storage_backend")
    @classmethod
    def validate_storage_backend(cls, v):
        """Validate storage backend"""
        valid_backends = ["memory", "redis"]
        if v not in valid_backends:
            raise ValueError(f"Storage backend must be one of {valid_backends}, got '{v}'")
        return v
        
    def configure_logging(self):
        """Configure logging based on settings"""
        logging.basicConfig(
            level=getattr(logging, self.log_level),
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            force=True  # Override any existing configuration
        )
        logger.info(f"Logging configured with level: {self.log_level}")
        
    def print_config(self):
        """Print configuration values (excluding sensitive data)"""
        logger.info("=== Voltie OCPP UDP Client Configuration ===")
        logger.info(f"UDP Server: {self.udp_host}:{self.udp_port}")
        logger.info(f"Backend URL: {self.backend_url}")
        logger.info(f"Driver: {self.driver}")
        logger.info(f"Storage Backend: {self.storage_backend}")
        if self.storage_backend == "redis":
            logger.info(f"Redis: {self.redis_host}:{self.redis_port}/{self.redis_db}")
        logger.info(f"Log Level: {self.log_level}")
        if self.api_enabled:
            logger.info(f"Admin API: {self.api_host}:{self.api_port}")
        else:
            logger.info("Admin API: Disabled")
        logger.info("============================================")


# Global configuration instance
_config: Optional[Config] = None


def get_config() -> Config:
    """
    Get the global configuration instance.
    Loads configuration on first call.
    """
    global _config
    
    if _config is None:
        try:
            _config = Config()
            _config.configure_logging()
            logger.info("Configuration loaded successfully")
        except Exception as e:
            error_msg = f"Failed to load configuration: {e}"
            print(f"ERROR: {error_msg}")  # Print to stdout since logging might not be configured
            raise RuntimeError(error_msg) from e
            
    return _config


def reload_config() -> Config:
    """
    Reload the configuration (useful for testing or config changes)
    """
    global _config
    _config = None
    return get_config()


def validate_required_config():
    """
    Validate that all required configuration is present
    Raises clear errors for missing required configs
    """
    try:
        config = get_config()
        
        # Check required fields
        if not config.backend_url:
            raise ValueError("BACKEND_URL is required but not set")
            
        logger.info("Configuration validation passed")
        return True
        
    except Exception as e:
        error_msg = f"Configuration validation failed: {e}"
        logger.error(error_msg)
        raise RuntimeError(error_msg) from e


if __name__ == "__main__":
    # Test configuration loading
    try:
        config = get_config()
        config.print_config()
        validate_required_config()
        print("Configuration test successful!")
    except Exception as e:
        print(f"Configuration test failed: {e}")
        exit(1)
