"""
Gestionnaire de configuration pour le SDK Lescopr
"""
import json
import os
from typing import Dict, Optional, Any
from pathlib import Path

from .validator import ConfigValidator
from ...monitoring.logger import logger


class ConfigManager:
    """Gestionnaire de configuration du SDK Lescopr"""
    
    CONFIG_FILENAME = '.lescopr.json'
    
    def __init__(self, config_dir: Optional[str] = None):
        self.config_dir = Path(config_dir or os.getcwd())
        self.config_file = self.config_dir / self.CONFIG_FILENAME
        self.validator = ConfigValidator()
    
    def exists(self) -> bool:
        """Vérifie si le fichier de configuration existe"""
        return self.config_file.exists() and self.config_file.is_file()
    
    def load(self) -> Dict[str, Any]:
        """
        Charge la configuration depuis le fichier
        
        Returns:
            Configuration chargée ou dictionnaire vide si erreur
        """
        if not self.exists():
            logger('info', "Aucun fichier de configuration trouvé")
            return {}
        
        try:
            with open(self.config_file, 'r', encoding='utf-8') as f:
                config = json.load(f)
            
            if not isinstance(config, dict):
                logger('error', "Format de configuration invalide")
                return {}
            
            # Valider la configuration chargée
            if self.validator.validate(config):
                logger('success', "Configuration chargée et validée avec succès")
                return config
            else:
                errors = self.validator.get_validation_errors(config)
                logger('warning', f"Configuration invalide: {'; '.join(errors)}")
                return config  # Retourner quand même pour permettre la migration
                
        except json.JSONDecodeError as e:
            logger('error', f"Fichier de configuration JSON invalide: {e}")
            return {}
        except Exception as e:
            logger('error', f"Erreur lors du chargement de la configuration: {e}")
            return {}
    
    def save(self, config: Dict[str, Any], merge: bool = True) -> bool:
        """
        Sauvegarde la configuration
        
        Args:
            config: Configuration à sauvegarder
            merge: Si True, fusionne avec la configuration existante
            
        Returns:
            True si succès, False sinon
        """
        try:
            # Préparer la configuration finale
            if merge:
                existing_config = self.load()
                final_config = {**existing_config, **config}
            else:
                final_config = config.copy()
            
            # Valider avant sauvegarde
            validation_errors = self.validator.get_validation_errors(final_config)
            if validation_errors:
                logger('error', f"Configuration invalide: {'; '.join(validation_errors)}")
                return False
            
            # Créer le répertoire si nécessaire
            self.config_dir.mkdir(parents=True, exist_ok=True)
            
            # Sauvegarder avec formatage propre
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(final_config, f, indent=4, ensure_ascii=False, sort_keys=True)
            
            logger('success', f"Configuration sauvegardée dans {self.config_file}")
            return True
            
        except PermissionError:
            logger('error', f"Permission refusée pour écrire dans {self.config_file}")
            return False
        except Exception as e:
            logger('error', f"Erreur lors de la sauvegarde: {e}")
            return False
    
    def update(self, updates: Dict[str, Any]) -> bool:
        """
        Met à jour des champs spécifiques de la configuration
        
        Args:
            updates: Dictionnaire des champs à mettre à jour
            
        Returns:
            True si succès, False sinon
        """
        # Valider les updates partiellement
        if not self.validator.validate_partial(updates):
            logger('error', "Mises à jour de configuration invalides")
            return False
        
        return self.save(updates, merge=True)
    
    def delete(self) -> bool:
        """
        Supprime le fichier de configuration
        
        Returns:
            True si succès, False sinon
        """
        try:
            if self.exists():
                self.config_file.unlink()
                logger('success', "Configuration supprimée")
                return True
            else:
                logger('warning', "Aucun fichier de configuration à supprimer")
                return False
        except PermissionError:
            logger('error', f"Permission refusée pour supprimer {self.config_file}")
            return False
        except Exception as e:
            logger('error', f"Erreur lors de la suppression: {e}")
            return False
    
    def get_config_path(self) -> str:
        """Retourne le chemin absolu du fichier de configuration"""
        return str(self.config_file.absolute())
    
    def backup(self, backup_suffix: str = '.backup') -> bool:
        """
        Crée une sauvegarde de la configuration actuelle
        
        Args:
            backup_suffix: Suffixe à ajouter au nom du fichier de sauvegarde
            
        Returns:
            True si succès, False sinon
        """
        if not self.exists():
            logger('warning', "Aucune configuration à sauvegarder")
            return False
        
        try:
            backup_file = self.config_file.with_suffix(self.config_file.suffix + backup_suffix)
            
            # Copier le fichier
            import shutil
            shutil.copy2(self.config_file, backup_file)
            
            logger('success', f"Sauvegarde créée: {backup_file}")
            return True
            
        except Exception as e:
            logger('error', f"Erreur lors de la création de la sauvegarde: {e}")
            return False
    
    def restore_backup(self, backup_suffix: str = '.backup') -> bool:
        """
        Restaure une sauvegarde de configuration
        
        Args:
            backup_suffix: Suffixe du fichier de sauvegarde
            
        Returns:
            True si succès, False sinon
        """
        backup_file = self.config_file.with_suffix(self.config_file.suffix + backup_suffix)
        
        if not backup_file.exists():
            logger('error', f"Fichier de sauvegarde introuvable: {backup_file}")
            return False
        
        try:
            import shutil
            shutil.copy2(backup_file, self.config_file)
            
            logger('success', f"Configuration restaurée depuis {backup_file}")
            return True
            
        except Exception as e:
            logger('error', f"Erreur lors de la restauration: {e}")
            return False