#!/usr/bin/env python3
"""
Configuration Loader Module for iPod Nano Transfer Tool
Handles reading and writing configuration settings
"""

import os
import logging
import configparser
from pathlib import Path
from typing import Any, Dict, Optional

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


class ConfigLoader:
    """Class to handle configuration loading and saving"""
    
    def __init__(self, config_file: Optional[str] = None):
        """
        Initialize the configuration loader

        Args:
            config_file: Path to configuration file (optional)
        """
        if not config_file:
            self.config_file = os.path.join(
                os.path.expanduser("~"), ".config", "neo-pod-desktop", "config.ini"
            )
            self._migrate_old_config()
        else:
            self.config_file = config_file

        self.config = configparser.ConfigParser()

        # Load configuration
        self.load()

    def _migrate_old_config(self):
        """Migrate config from old project-root location to XDG config dir."""
        old_path = os.path.join(
            os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
            "config.ini"
        )
        if os.path.exists(old_path) and not os.path.exists(self.config_file):
            logger.info("Migrating config from %s to %s", old_path, self.config_file)
            os.makedirs(os.path.dirname(self.config_file), exist_ok=True)
            os.rename(old_path, self.config_file)
    
    def load(self) -> bool:
        """
        Load configuration from file
        
        Returns:
            True if successful, False otherwise
        """
        try:
            if os.path.exists(self.config_file):
                logger.info(f"Loading configuration from {self.config_file}")
                self.config.read(self.config_file)
            else:
                logger.warning(f"Configuration file {self.config_file} not found, using defaults")
            self._set_defaults()
            return True
        except Exception as e:
            logger.error(f"Failed to load configuration: {e}")
            self._set_defaults()
            return False
    
    def save(self) -> bool:
        """
        Save configuration to file

        Returns:
            True if successful, False otherwise
        """
        try:
            logger.info(f"Saving configuration to {self.config_file}")
            os.makedirs(os.path.dirname(self.config_file), exist_ok=True)

            with open(self.config_file, 'w') as f:
                self.config.write(f)

            return True
        except Exception as e:
            logger.error(f"Failed to save configuration: {e}")
            return False
    
    def _set_defaults(self):
        """Set default configuration values"""
        # General section
        if not self.config.has_section('General'):
            self.config.add_section('General')
            
        if not self.config.has_option('General', 'output_dir'):
            self.config.set('General', 'output_dir', os.path.join(os.path.expanduser("~"), "Music", "iPod"))
        if not self.config.has_option('General', 'format'):
            self.config.set('General', 'format', 'm4a')
        if not self.config.has_option('General', 'quality'):
            self.config.set('General', 'quality', '256')
        
        # Video section
        if not self.config.has_section('Video'):
            self.config.add_section('Video')
            
        if not self.config.has_option('Video', 'enable_video'):
            self.config.set('Video', 'enable_video', 'false')
        if not self.config.has_option('Video', 'resolution'):
            self.config.set('Video', 'resolution', '640x480')
        
        # Metadata section
        if not self.config.has_section('Metadata'):
            self.config.add_section('Metadata')
            
        if not self.config.has_option('Metadata', 'embed_artwork'):
            self.config.set('Metadata', 'embed_artwork', 'true')
        
        # Device section
        if not self.config.has_section('Device'):
            self.config.add_section('Device')
            
        if not self.config.has_option('Device', 'auto_detect'):
            self.config.set('Device', 'auto_detect', 'true')
        if not self.config.has_option('Device', 'mount_point'):
            self.config.set('Device', 'mount_point', '')
        
        # Advanced section
        if not self.config.has_section('Advanced'):
            self.config.add_section('Advanced')
            
        if not self.config.has_option('Advanced', 'temp_dir'):
            self.config.set('Advanced', 'temp_dir', 'temp')
        if not self.config.has_option('Advanced', 'clean_temp'):
            self.config.set('Advanced', 'clean_temp', 'true')
        if not self.config.has_option('Advanced', 'hide_library_buttons'):
            self.config.set('Advanced', 'hide_library_buttons', 'false')

        # Hotkeys section
        if not self.config.has_section('Hotkeys'):
            self.config.add_section('Hotkeys')

        hotkey_defaults = {
            'play_pause': 'Space',
            'prev_track': 'Ctrl+Left',
            'next_track': 'Ctrl+Right',
            'volume_up': 'Ctrl+Up',
            'volume_down': 'Ctrl+Down',
            'seek_forward': 'Right',
            'seek_backward': 'Left',
            'tab_library': 'Ctrl+1',
            'tab_ipod': 'Ctrl+2',
            'tab_settings': 'Ctrl+3',
            'search_focus': 'Ctrl+F',
            'select_all': 'Ctrl+A',
            'library_refresh': 'F5',
            'ipod_refresh': 'Ctrl+R',
            'delete_selected': 'Delete',
            'library_add_files': 'Ctrl+O',
        }
        for key, value in hotkey_defaults.items():
            if not self.config.has_option('Hotkeys', key):
                self.config.set('Hotkeys', key, value)

        # Playback section is DEPRECATED — session state moved to
        # session.json in ~/.local/share/. The defaults below are
        # kept only for backward-compatible reads during migration.
        # All new code should use SessionStore instead.
        if not self.config.has_section('Playback'):
            self.config.add_section('Playback')
    
    def get(self, section: str, option: str, fallback: Any = None) -> Any:
        """
        Get configuration value
        
        Args:
            section: Configuration section
            option: Configuration option
            fallback: Fallback value if option not found
            
        Returns:
            Configuration value
        """
        try:
            return self.config.get(section, option, fallback=fallback)
        except (configparser.NoSectionError, configparser.NoOptionError):
            return fallback
    
    def get_boolean(self, section: str, option: str, fallback: bool = False) -> bool:
        """
        Get boolean configuration value
        
        Args:
            section: Configuration section
            option: Configuration option
            fallback: Fallback value if option not found
            
        Returns:
            Boolean configuration value
        """
        try:
            return self.config.getboolean(section, option, fallback=fallback)
        except (configparser.NoSectionError, configparser.NoOptionError):
            return fallback
    
    def get_int(self, section: str, option: str, fallback: int = 0) -> int:
        """
        Get integer configuration value
        
        Args:
            section: Configuration section
            option: Configuration option
            fallback: Fallback value if option not found
            
        Returns:
            Integer configuration value
        """
        try:
            return self.config.getint(section, option, fallback=fallback)
        except (configparser.NoSectionError, configparser.NoOptionError):
            return fallback
    
    def get_float(self, section: str, option: str, fallback: float = 0.0) -> float:
        """
        Get float configuration value
        
        Args:
            section: Configuration section
            option: Configuration option
            fallback: Fallback value if option not found
            
        Returns:
            Float configuration value
        """
        try:
            return self.config.getfloat(section, option, fallback=fallback)
        except (configparser.NoSectionError, configparser.NoOptionError):
            return fallback
    
    def set(self, section: str, option: str, value: Any) -> None:
        """
        Set configuration value
        
        Args:
            section: Configuration section
            option: Configuration option
            value: Configuration value
        """
        if not self.config.has_section(section):
            self.config.add_section(section)
            
        self.config.set(section, option, str(value))
    
    def get_all(self) -> Dict[str, Dict[str, str]]:
        """
        Get all configuration values
        
        Returns:
            Dictionary of all configuration values
        """
        result = {}
        
        for section in self.config.sections():
            result[section] = {}
            
            for option in self.config.options(section):
                result[section][option] = self.config.get(section, option)
                
        return result


if __name__ == "__main__":
    # Example usage
    config = ConfigLoader()
    
    # Get configuration values
    output_dir = config.get('General', 'output_dir')
    format = config.get('General', 'format')
    quality = config.get_int('General', 'quality')
    
    print(f"Output directory: {output_dir}")
    print(f"Format: {format}")
    print(f"Quality: {quality} kbps")
    
    # Set configuration value
    config.set('General', 'format', 'mp3')
    
    # Save configuration
    config.save()
