"""
AbuLang Lazy Loader - Load modules only when needed
"""

from typing import Dict, Any, Optional, Callable
import importlib
import sys


class LazyModule:
    """Lazy-loaded module wrapper"""
    
    def __init__(self, module_name: str):
        self.module_name = module_name
        self._module = None
        self._loaded = False
    
    def _load(self):
        """Load module on first access"""
        if not self._loaded:
            try:
                self._module = importlib.import_module(self.module_name)
                self._loaded = True
            except ImportError as e:
                raise ImportError(f"Failed to load module: {self.module_name}") from e
    
    def __getattr__(self, name: str) -> Any:
        """Get attribute from module, loading if necessary"""
        if not self._loaded:
            self._load()
        return getattr(self._module, name)
    
    def __call__(self, *args, **kwargs):
        """Call module if it's callable"""
        if not self._loaded:
            self._load()
        return self._module(*args, **kwargs)


class LazyLoader:
    """Manages lazy loading of modules"""
    
    def __init__(self):
        self.lazy_modules: Dict[str, LazyModule] = {}
        self.loaded_modules: Dict[str, Any] = {}
    
    def register_lazy(self, alias: str, module_name: str):
        """Register a module for lazy loading"""
        self.lazy_modules[alias] = LazyModule(module_name)
    
    def get_module(self, alias: str) -> Any:
        """Get module (loads if necessary)"""
        if alias in self.lazy_modules:
            return self.lazy_modules[alias]
        elif alias in self.loaded_modules:
            return self.loaded_modules[alias]
        else:
            raise KeyError(f"Module not found: {alias}")
    
    def preload(self, alias: str):
        """Preload a lazy module"""
        if alias in self.lazy_modules:
            module = self.lazy_modules[alias]
            module._load()
            self.loaded_modules[alias] = module._module
    
    def preload_all(self):
        """Preload all lazy modules"""
        for alias in list(self.lazy_modules.keys()):
            self.preload(alias)
    
    def get_stats(self) -> Dict:
        """Get lazy loading statistics"""
        return {
            "registered": len(self.lazy_modules),
            "loaded": len(self.loaded_modules),
            "pending": len(self.lazy_modules) - len(self.loaded_modules)
        }


class LazyContext:
    """Context manager for lazy-loaded modules"""
    
    def __init__(self):
        self.loader = LazyLoader()
        self._setup_common_modules()
    
    def _setup_common_modules(self):
        """Setup common Python modules for lazy loading"""
        common_modules = {
            'math': 'math',
            'random': 'random',
            'datetime': 'datetime',
            'json': 'json',
            're': 're',
            'os': 'os',
            'sys': 'sys',
            'collections': 'collections',
            'itertools': 'itertools',
            'functools': 'functools',
        }
        
        for alias, module_name in common_modules.items():
            self.loader.register_lazy(alias, module_name)
    
    def __getattr__(self, name: str) -> Any:
        """Get module from context"""
        return self.loader.get_module(name)


# Global lazy context
_lazy_context = LazyContext()


def get_lazy_context() -> LazyContext:
    """Get global lazy context"""
    return _lazy_context
