"""Configuration Validation Module"""
import os
import json
import logging
from typing import Dict, List, Any, Optional
from pathlib import Path
from pydantic import ValidationError

from src.services.provider.registry import ServiceConfig

logger = logging.getLogger(__name__)


class ConfigValidator:
    """Validates service configurations"""
    
    @staticmethod
    def validate_config_file(file_path: str) -> tuple[bool, List[str]]:
        """Validate a configuration file.
        
        Args:
            file_path: Path to configuration file
            
        Returns:
            Tuple of (is_valid, error_messages)
        """
        errors = []
        
        # Check file exists
        if not os.path.exists(file_path):
            errors.append(f"Configuration file not found: {file_path}")
            return False, errors
        
        # Check file is readable
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
        except json.JSONDecodeError as e:
            errors.append(f"Invalid JSON in {file_path}: {e}")
            return False, errors
        except Exception as e:
            errors.append(f"Error reading {file_path}: {e}")
            return False, errors
        
        # Validate it's a list
        if not isinstance(data, list):
            errors.append(f"Configuration must be a list, got {type(data).__name__}")
            return False, errors
        
        # Validate each service config
        for idx, config in enumerate(data):
            try:
                ServiceConfig(**config)
            except ValidationError as e:
                errors.append(f"Service {idx} ({config.get('id', 'unknown')}): {e}")
        
        return len(errors) == 0, errors
    
    @staticmethod
    def validate_config_directory(dir_path: str) -> Dict[str, tuple[bool, List[str]]]:
        """Validate all configuration files in a directory.
        
        Args:
            dir_path: Path to configuration directory
            
        Returns:
            Dict mapping filename to (is_valid, error_messages)
        """
        results = {}
        
        if not os.path.exists(dir_path):
            logger.error(f"Configuration directory not found: {dir_path}")
            return results
        
        for filename in os.listdir(dir_path):
            if filename.endswith('.json') and filename != 'default.json':
                file_path = os.path.join(dir_path, filename)
                is_valid, errors = ConfigValidator.validate_config_file(file_path)
                results[filename] = (is_valid, errors)
        
        return results
    
    @staticmethod
    def validate_service_config(config: Dict[str, Any]) -> tuple[bool, Optional[str]]:
        """Validate a single service configuration.
        
        Args:
            config: Service configuration dictionary
            
        Returns:
            Tuple of (is_valid, error_message)
        """
        try:
            ServiceConfig(**config)
            return True, None
        except ValidationError as e:
            return False, str(e)
    
    @staticmethod
    def check_module_exists(module_path: str) -> bool:
        """
        Check if a module can be imported.
        
        Args:
            module_path: Python module path (e.g., 'src.services.provider.dashscope.llm')
            
        Returns:
            True if module exists and can be imported
        """
        try:
            # Try with 'backend.' prefix
            import importlib
            try:
                importlib.import_module(module_path)
                return True
            except ImportError:
                # Try without 'backend.' prefix if it starts with it
                if module_path.startswith('backend.'):
                    alt_path = module_path.replace('backend.', '', 1)
                    importlib.import_module(alt_path)
                    return True
                return False
        except Exception as e:
            logger.debug(f"Module check failed for {module_path}: {e}")
            return False
    
    @staticmethod
    def check_class_exists(module_path: str, class_name: str) -> bool:
        """
        Check if a class exists in a module.
        
        Args:
            module_path: Python module path
            class_name: Class name
            
        Returns:
            True if class exists
        """
        try:
            import importlib
            
            # Try original path
            try:
                module = importlib.import_module(module_path)
            except ImportError:
                # Try alternative path
                if module_path.startswith('backend.'):
                    alt_path = module_path.replace('backend.', '', 1)
                    module = importlib.import_module(alt_path)
                else:
                    return False
            
            return hasattr(module, class_name)
        except Exception as e:
            logger.debug(f"Class check failed for {module_path}.{class_name}: {e}")
            return False
    
    @staticmethod
    def validate_config_deep(config: Dict[str, Any]) -> tuple[bool, List[str]]:
        """
        Perform deep validation including module and class checks.
        
        Args:
            config: Service configuration dictionary
            
        Returns:
            Tuple of (is_valid, error_messages)
        """
        errors = []
        
        # Basic validation
        is_valid, error = ConfigValidator.validate_service_config(config)
        if not is_valid:
            errors.append(f"Schema validation failed: {error}")
            return False, errors
        
        # Check module exists
        module_path = config.get('module')
        if module_path and not ConfigValidator.check_module_exists(module_path):
            errors.append(f"Module not found: {module_path}")
        
        # Check class exists
        class_name = config.get('class')
        if module_path and class_name:
            if not ConfigValidator.check_class_exists(module_path, class_name):
                errors.append(f"Class {class_name} not found in module {module_path}")
        
        return len(errors) == 0, errors
    
    @staticmethod
    def generate_validation_report(dir_path: str) -> Dict[str, Any]:
        """Generate a comprehensive validation report for all configurations.
        
        Args:
            dir_path: Path to configuration directory
            
        Returns:
            Validation report dictionary
        """
        results = ConfigValidator.validate_config_directory(dir_path)
        
        total_files = len(results)
        valid_files = sum(1 for is_valid, _ in results.values() if is_valid)
        invalid_files = total_files - valid_files
        
        all_errors = []
        for filename, (is_valid, errors) in results.items():
            if not is_valid:
                all_errors.extend([f"{filename}: {err}" for err in errors])
        
        return {
            "total_files": total_files,
            "valid_files": valid_files,
            "invalid_files": invalid_files,
            "success_rate": (valid_files / total_files * 100) if total_files > 0 else 0,
            "errors": all_errors,
            "details": {
                filename: {
                    "valid": is_valid,
                    "errors": errors
                }
                for filename, (is_valid, errors) in results.items()
            }
        }


def validate_all_configs(config_dir: str = None) -> Dict[str, Any]:
    """
    Convenience function to validate all configurations.
    
    Args:
        config_dir: Configuration directory path (defaults to src/config/services)
        
    Returns:
        Validation report
    """
    if config_dir is None:
        # Default to src/config/services
        base_dir = Path(__file__).parent.parent.parent
        config_dir = base_dir / "config" / "services"
    
    return ConfigValidator.generate_validation_report(str(config_dir))
