"""Configuration management for ADS1115 application."""

import os
import yaml
from dataclasses import dataclass, asdict
from typing import Optional, Dict, Any
from pathlib import Path


@dataclass
class AppConfig:
    """Application configuration."""
    # I2C Settings
    i2c_address: int = 0x48
    i2c_bus: int = 1
    
    # ADC Settings
    gain: float = 1.0
    data_rate: int = 128
    mode: str = "single"
    
    # API Settings
    api_host: str = "0.0.0.0"
    api_port: int = 8000
    
    # Logging
    log_level: str = "INFO"
    log_file: Optional[str] = None
    
    # Mock mode (for testing without hardware)
    mock_mode: bool = False
    
    # Default data directory
    data_dir: str = "./data"


class ConfigManager:
    """Manage application configuration from file and environment."""
    
    DEFAULT_CONFIG_FILE = "config.yaml"
    
    def __init__(self, config_file: Optional[str] = None):
        self.config_file = config_file or self.DEFAULT_CONFIG_FILE
        self._config: Optional[AppConfig] = None
    
    def load(self) -> AppConfig:
        """Load configuration from file and environment."""
        # Start with defaults
        config = AppConfig()
        
        # Load from file if exists
        if os.path.exists(self.config_file):
            with open(self.config_file, 'r') as f:
                data = yaml.safe_load(f)
                if data:
                    config = self._dict_to_config(data)
        
        # Override with environment variables
        config = self._apply_env_overrides(config)
        
        self._config = config
        return config
    
    def save(self, config: Optional[AppConfig] = None) -> None:
        """Save configuration to file."""
        config = config or self._config or AppConfig()
        
        data = asdict(config)
        with open(self.config_file, 'w') as f:
            yaml.dump(data, f, default_flow_style=False)
    
    def _dict_to_config(self, data: Dict[str, Any]) -> AppConfig:
        """Convert dictionary to AppConfig."""
        # Filter only valid fields
        valid_fields = AppConfig.__dataclass_fields__.keys()
        filtered = {k: v for k, v in data.items() if k in valid_fields}
        return AppConfig(**filtered)
    
    def _apply_env_overrides(self, config: AppConfig) -> AppConfig:
        """Apply environment variable overrides."""
        env_mappings = {
            'ADS1115_I2C_ADDRESS': ('i2c_address', lambda x: int(x, 16) if x.startswith('0x') else int(x)),
            'ADS1115_I2C_BUS': ('i2c_bus', int),
            'ADS1115_GAIN': ('gain', float),
            'ADS1115_DATA_RATE': ('data_rate', int),
            'ADS1115_MODE': ('mode', str),
            'ADS1115_MOCK': ('mock_mode', lambda x: x.lower() in ('true', '1', 'yes')),
            'API_HOST': ('api_host', str),
            'API_PORT': ('api_port', int),
            'LOG_LEVEL': ('log_level', str),
            'LOG_FILE': ('log_file', str),
            'DATA_DIR': ('data_dir', str),
        }
        
        for env_var, (attr, converter) in env_mappings.items():
            value = os.getenv(env_var)
            if value is not None:
                setattr(config, attr, converter(value))
        
        return config
    
    def get_config(self) -> AppConfig:
        """Get current configuration, loading if necessary."""
        if self._config is None:
            self.load()
        return self._config


# Global instance
_config_manager: Optional[ConfigManager] = None


def get_config_manager() -> ConfigManager:
    """Get global config manager instance."""
    global _config_manager
    if _config_manager is None:
        _config_manager = ConfigManager()
    return _config_manager


def get_config() -> AppConfig:
    """Get current application configuration."""
    return get_config_manager().get_config()
