"""
Lescopr SDK - Auto-discovery UNIVERSEL
"""
import os
import sys
import threading
import logging
import atexit
import importlib
import builtins
from typing import Optional
from datetime import datetime

from .core.lescopr import Lescopr

__version__ = "0.1.0"
__author__ = "SonnaLab"

_auto_instance: Optional[Lescopr] = None
_setup_lock = threading.Lock()
_handler_installed = False
_global_hooks_installed = False
_setup_completed = False

# 🆕 CONTRÔLE DES PRINTS DE DEBUG
_debug_prints_enabled = False

def _debug_print(message: str):
    """Print conditionnel pour debug - peut être désactivé en production."""
    if _debug_prints_enabled:
        print(message)

def set_debug_mode():
    """Active les prints de debug Lescopr."""
    global _debug_prints_enabled
    _debug_prints_enabled = True


def is_debug_mode() -> bool:
    """Retourne l'état du mode debug."""
    return _debug_prints_enabled


# ✅ SAUVEGARDER L'ORIGINAL _gcd_import
_original_gcd_import = importlib._bootstrap._gcd_import

def _lescopr_gcd_import(name, package=None, level=0):
    """Hook _gcd_import pour capturer TOUTES les erreurs d'import."""
    try:
        return _original_gcd_import(name, package, level)
    except (ImportError, AttributeError) as e:
        _debug_print(f"🔴 GCD_IMPORT ERROR CAPTURED: {type(e).__name__}: {e}")
        _debug_print(f"🔴 NAME: {name}, PACKAGE: {package}, LEVEL: {level}")
        
        # ✅ IDENTIFIER LE TYPE D'ERREUR
        error_type = type(e).__name__
        if isinstance(e, AttributeError):
            _debug_print(f"🔴 CONVERTING AttributeError to ImportError")
            e = ImportError(f"cannot import name from '{name}' ({str(e)})")
        
        # ✅ TENTATIVE D'ENVOI IMMÉDIAT SI LESCOPR DISPONIBLE
        try:
            if _auto_instance and hasattr(_auto_instance, 'grpc_client'):
                log_entry = {
                    'timestamp': datetime.now().isoformat(),
                    'level': 'ERROR',
                    'message': f"Bootstrap Import Error: {error_type}: {e}",
                    'logger_name': 'bootstrap.gcd_import',
                    'module': name,
                    'source': 'bootstrap_import_hook',
                    'import_name': name,
                    'import_package': package,
                    'import_level': level,
                    'exception_type': error_type,
                    'force_send': True
                }
                
                result = _auto_instance.grpc_client.send_log('ERROR', log_entry['message'], log_entry)
                _debug_print(f"🔴 BOOTSTRAP HOOK SEND RESULT: {result}")
        except Exception as send_error:
            _debug_print(f"🔴 BOOTSTRAP HOOK SEND ERROR: {send_error}")
        
        # ✅ RE-LEVER L'EXCEPTION ORIGINALE
        raise

# ✅ INSTALLER LE HOOK _gcd_import IMMÉDIATEMENT
importlib._bootstrap._gcd_import = _lescopr_gcd_import

# GARDER AUSSI LE HOOK builtins.__import__ EXISTANT
_original_import = builtins.__import__

def _enhanced_global_import_hook(name, globals=None, locals=None, fromlist=(), level=0):
    """Hook d'import global renforcé - capture AttributeError et ImportError."""
    try:
        return _original_import(name, globals, locals, fromlist, level)
    except (ImportError, AttributeError) as e:
        _debug_print(f"🔴 GLOBAL IMPORT ERROR: {type(e).__name__}: {e}")
        _debug_print(f"🔴 MODULE: {name}, FROMLIST: {fromlist}")
        
        # ✅ TRANSFORMER AttributeError EN ImportError POUR UNIFORMITÉ
        if isinstance(e, AttributeError):
            _debug_print(f"🔴 CONVERTING AttributeError to ImportError")
            import_error = ImportError(f"cannot import name '{fromlist[0] if fromlist else 'unknown'}' from '{name}' ({str(e)})")
            import_error.__cause__ = e
            e = import_error
        
        # ✅ TENTATIVE D'ENVOI IMMÉDIAT SI LESCOPR DISPONIBLE
        try:
            if _auto_instance and hasattr(_auto_instance, 'grpc_client'):
                log_entry = {
                    'timestamp': datetime.now().isoformat(),
                    'level': 'ERROR',
                    'message': f"Global Import Error: {type(e).__name__}: {e}",
                    'logger_name': 'global.import_hook',
                    'module': name,
                    'source': 'global_import_hook',
                    'import_name': name,
                    'import_fromlist': list(fromlist) if fromlist else [],
                    'exception_type': type(e).__name__,
                    'force_send': True
                }
                
                result = _auto_instance.grpc_client.send_log('ERROR', log_entry['message'], log_entry)
                _debug_print(f"🔴 GLOBAL HOOK SEND RESULT: {result}")
        except Exception as send_error:
            _debug_print(f"🔴 GLOBAL HOOK SEND ERROR: {send_error}")
        
        # ✅ RE-LEVER L'EXCEPTION ORIGINALE
        raise e

# ✅ INSTALLER LES DEUX HOOKS
builtins.__import__ = _enhanced_global_import_hook


def logs():
    """Active la capture automatique des logs Lescopr."""
    global _auto_instance
    
    setup_key = f"LESCOPR_SETUP_{os.getpid()}"
    
    if os.environ.get(setup_key) == "true":
        return _auto_instance
    
    with _setup_lock:
        if os.environ.get(setup_key) == "true":
            return _auto_instance
        
        os.environ[setup_key] = "true"
        
        try:
            if _is_lescopr_daemon():
                return None

            if not _has_lescopr_config():
                return None

            instance = _setup_lescopr_instance()
            if instance:
                _auto_instance = instance
                _install_resilient_handlers(instance)
                return instance
            else:
                os.environ.pop(setup_key, None)
                
        except Exception as e:
            _debug_print(f"❌ Erreur Lescopr auto-discovery: {e}")
            os.environ.pop(setup_key, None)
    
    return None


def _install_resilient_handlers(lescopr_instance):
    """Installation robuste avec survie au rechargement Django."""
    global _global_hooks_installed
    if _global_hooks_installed:
        return
    
    try:
        _silence_lescopr_logs()
        
        # 🛡️ HANDLER RÉSILIENT
        class ResilientLescoprHandler(logging.Handler):
            def __init__(self, lescopr_client):
                super().__init__()
                self.lescopr_client = lescopr_client
                self.setLevel(logging.DEBUG)
                self.ignore_patterns = {
                    'lescopr', 'grpc', 'protobuf', 'asyncio',
                    'urllib3', 'requests.packages'
                }
            
            def emit(self, record):
                try:
                    if self._should_skip(record):
                        return
                    
                    is_critical_error = (
                        record.levelno >= logging.ERROR or
                        any(error_type in str(record.getMessage()).lower() 
                            for error_type in ['error', 'exception', 'traceback', 'import'])
                    )
                    
                    log_entry = {
                        'timestamp': datetime.fromtimestamp(record.created).isoformat(),
                        'level': record.levelname,
                        'message': record.getMessage()[:1500],
                        'logger_name': record.name,
                        'module': getattr(record, 'module', 'unknown'),
                        'function': getattr(record, 'funcName', 'unknown'),
                        'line': getattr(record, 'lineno', 0),
                        'source': 'resilient_handler',
                        'is_critical': is_critical_error
                    }
                    
                    if record.exc_info:
                        import traceback
                        log_entry['exception'] = traceback.format_exception(*record.exc_info)[:2000]
                        log_entry['level'] = 'ERROR'
                    
                    if is_critical_error:
                        log_entry['force_send'] = True
                    
                    _debug_print(f"🔴 RESILIENT HANDLER CAPTURED: {record.levelname} - {record.getMessage()}")
                    self._send_to_daemon(log_entry)
                    
                except Exception as e:
                    _debug_print(f"🔴 RESILIENT HANDLER ERROR: {e}")
            
            def _should_skip(self, record):
                logger_name = record.name.lower()
                message = record.getMessage().lower()
                
                # ✅ JAMAIS FILTRER LES ERREURS
                if record.levelno >= logging.ERROR or record.exc_info is not None:
                    return False
                
                # ✅ FILTRER SEULEMENT LE BRUIT
                return any(pattern in logger_name or pattern in message 
                          for pattern in self.ignore_patterns)
            
            def _send_to_daemon(self, log_entry):
                try:
                    if (self.lescopr_client and 
                        hasattr(self.lescopr_client, 'grpc_client') and
                        self.lescopr_client.grpc_client and
                        self.lescopr_client.grpc_client.is_connected()):
                        
                        result = self.lescopr_client.grpc_client.send_log(
                            log_entry['level'],
                            log_entry['message'],
                            log_entry
                        )
                        _debug_print(f"🔴 RESILIENT SEND RESULT: {result}")
                        return result
                except Exception as e:
                    _debug_print(f"🔴 RESILIENT SEND ERROR: {e}")
                return False
        
        # ✅ VÉRIFIER SI HANDLER DÉJÀ INSTALLÉ
        root_logger = logging.getLogger()
        for existing_handler in root_logger.handlers:
            if isinstance(existing_handler, ResilientLescoprHandler):
                _debug_print("🔴 RESILIENT HANDLER ALREADY INSTALLED")
                return
        
        # ✅ INSTALLER LE HANDLER RÉSILIENT
        handler = ResilientLescoprHandler(lescopr_instance)
        root_logger.addHandler(handler)
        root_logger.setLevel(logging.DEBUG)
        
        # 🔄 MONKEY-PATCH DJANGO LOGGING POUR RÉINSTALLATION AUTO
        try:
            from django.utils.log import configure_logging
            original_configure = configure_logging
            
            def patched_configure_logging(*args, **kwargs):
                original_configure(*args, **kwargs)
                # ✅ RÉINSTALLER APRÈS RESET DJANGO
                root_logger = logging.getLogger()
                if not any(isinstance(h, ResilientLescoprHandler) for h in root_logger.handlers):
                    root_logger.addHandler(handler)
                    _debug_print("🔴 HANDLER REINSTALLED AFTER DJANGO RESET")
            
            # ✅ REMPLACER LA FONCTION DJANGO
            import django.utils.log
            django.utils.log.configure_logging = patched_configure_logging
            _debug_print("🔴 DJANGO LOGGING MONKEY-PATCHED")
            
        except ImportError:
            _debug_print("🔴 DJANGO NOT AVAILABLE - SKIPPING LOGGING PATCH")
        
        # 🎯 HOOK DJANGO SIGNALS POUR EXCEPTIONS
        try:
            from django.core import signals
            
            def django_exception_hook(sender, **kwargs):
                """Capture les exceptions dans Django."""
                if 'exception' in kwargs:
                    exc = kwargs['exception']
                    _debug_print(f"🔴 DJANGO SIGNAL EXCEPTION: {exc}")
                    
                    if lescopr_instance and hasattr(lescopr_instance, 'grpc_client'):
                        log_entry = {
                            'timestamp': datetime.now().isoformat(),
                            'level': 'ERROR',
                            'message': f"Django Exception: {type(exc).__name__}: {exc}",
                            'source': 'django_signal',
                            'exception_type': type(exc).__name__,
                            'force_send': True
                        }
                        result = lescopr_instance.grpc_client.send_log('ERROR', log_entry['message'], log_entry)
                        _debug_print(f"🔴 DJANGO SIGNAL SEND RESULT: {result}")
            
            signals.got_request_exception.connect(django_exception_hook)
            _debug_print("🔴 DJANGO EXCEPTION SIGNALS CONNECTED")
            
        except ImportError:
            _debug_print("🔴 DJANGO SIGNALS NOT AVAILABLE")
        
        _debug_print("🔴 RESILIENT LESCOPR HOOKS INSTALLED ✅")
        _global_hooks_installed = True
        
    except Exception as e:
        _debug_print(f"🔴 RESILIENT HANDLER INSTALL ERROR: {e}")


def force_setup() -> Optional[Lescopr]:
    """Force un nouveau setup (debug uniquement)."""
    global _auto_instance
    
    _auto_instance = None
    setup_key = f"LESCOPR_SETUP_{os.getpid()}"
    os.environ.pop(setup_key, None)
    
    return logs()


def _cleanup_on_exit():
    """Nettoyage à la fermeture."""
    global _auto_instance
    try:
        if (_auto_instance and 
            hasattr(_auto_instance, 'grpc_client') and
            _auto_instance.grpc_client):
            _auto_instance.grpc_client.disconnect()
        
        setup_key = f"LESCOPR_SETUP_{os.getpid()}"
        os.environ.pop(setup_key, None)
        
    except Exception:
        pass


def _setup_lescopr_instance():
    """Setup silencieux de l'instance Lescopr."""
    try:
        if not _daemon_is_running():
            return None
        
        config = Lescopr._load_project_config()
        if not config:
            return None
        
        instance = Lescopr(
            api_key=config.get("api_key"),
            sdk_key=config.get("sdk_key"),
            environment=config.get("environment", "development"),
            auto_logging=False,
            auto_grpc=False,
        )
        
        instance.sdk_id = config.get("sdk_id")
        instance.project_name = config.get("project_name")
        instance.project_stack = config.get("project_stack", [])
        
        if instance.attach_to_daemon():
            return instance
        else:
            return None

    except Exception:
        return None


def _is_lescopr_daemon() -> bool:
    """Détecte si on est dans le daemon Lescopr."""
    return (
        'lescopr.daemon' in sys.modules or
        any('lescopr' in str(arg) and 'daemon' in str(arg) for arg in sys.argv) or
        os.environ.get('LESCOPR_DAEMON_MODE') == 'true'
    )


def _daemon_is_running() -> bool:
    """Vérifie si le daemon Lescopr est actif (via psutil ou test socket)."""
    try:
        import psutil
        
        pid_file = os.path.join(os.getcwd(), '.lescopr.pid')
        if not os.path.exists(pid_file):
            return False
        
        with open(pid_file, 'r') as f:
            pid = int(f.read().strip())
        
        if psutil.pid_exists(pid):
            try:
                process = psutil.Process(pid)
                cmdline = ' '.join(process.cmdline())
                return 'lescopr' in cmdline and 'daemon' in cmdline
            except (psutil.NoSuchProcess, psutil.AccessDenied):
                return False
        
        return False
        
    except (ImportError, Exception):
        return _test_daemon_port()


def _test_daemon_port() -> bool:
    """Test de connexion sur le port gRPC du daemon."""
    try:
        import socket
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(1)
        result = sock.connect_ex(('127.0.0.1', 50051))
        sock.close()
        return result == 0
    except Exception:
        return False


def _has_lescopr_config() -> bool:
    """Vérifie la présence de .lescopr.json."""
    try:
        config_file = os.path.join(os.getcwd(), '.lescopr.json')
        return os.path.exists(config_file)
    except Exception:
        return False


def _silence_lescopr_logs():
    """Évite les boucles de logs en filtrant ceux du propre logger Lescopr."""
    try:
        lescopr_logger = logging.getLogger('lescopr')
        lescopr_logger.handlers.clear()
        lescopr_logger.propagate = False
        lescopr_logger.setLevel(logging.CRITICAL + 10)
    except Exception:
        pass


def get_instance() -> Optional[Lescopr]:
    """Retourne l'instance auto-découverte (ou None)."""
    return _auto_instance


def is_active() -> bool:
    """Indique si Lescopr est actif et le handler attaché."""
    return _auto_instance is not None and _handler_installed


atexit.register(_cleanup_on_exit)


# ✅ EXPORTS PUBLIQUES
__all__ = [
    'Lescopr',
    'logs',
    'get_instance',
    'is_active',
    'force_setup',
    'set_debug_mode',
    'is_debug_mode', 
    '__version__',
    '__author__'
]