import os
import asyncio
import signal
from bullmq import Worker
import logging

# Configurar logging básico
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class ConsumerBullMQ:
    """
    Consumer simplificado para BullMQ que ejecuta cualquier función de procesamiento.
    """
    
    def __init__(self, worker_name: str, function_process, redis_url: str = None):
        self.worker_name = worker_name
        self.function_process = function_process
        self.redis_url = redis_url or os.environ.get('REDIS_HOST', 'redis://192.168.1.163:6379')
        self.worker = None
        self.running = False
        
    async def process_job(self, job, job_token):
        """Procesa el trabajo ejecutando la función proporcionada."""
        try:
            # Log en el dashboard de BullMQ - inicio del procesamiento
            await job.log(f"🚀 Started processing job {job.id}")
            await job.log(f"📋 Job data: {job.data}")
            
            logger.info(f"Processing job {job.id}")
            
            # Log del progreso
            await job.updateProgress(10)
            await job.log("⚙️ Executing processing function...")
            
            result = self.function_process(job.data)
            
            # Log de éxito
            await job.updateProgress(100)
            await job.log(f"✅ Job {job.id} completed successfully")
            await job.log(f"📤 Result: {result}")
            
            logger.info(f"Job {job.id} completed")
            return result
        except Exception as e:
            import traceback
            error_message = f"Job {job.id} failed: {str(e)}"
            error_details = traceback.format_exc()
            
            # Log del error en el dashboard de BullMQ
            await job.log(f"❌ Job {job.id} failed with error: {type(e).__name__}")
            await job.log(f"🔍 Error message: {str(e)}")
            await job.log(f"📍 Traceback details:")
            
            # Dividir el traceback en líneas para mejor visualización
            traceback_lines = error_details.split('\n')
            for line in traceback_lines[:10]:  # Limitar a las primeras 10 líneas
                if line.strip():
                    await job.log(f"  {line}")
            
            if len(traceback_lines) > 10:
                await job.log(f"  ... ({len(traceback_lines) - 10} more lines)")
            
            logger.error(f"{error_message}\n{error_details}")
            
            # Crear una nueva excepción con información detallada para BullMQ
            detailed_error = Exception(f"{type(e).__name__}: {str(e)}\n\nTraceback:\n{error_details}")
            raise detailed_error
    
    def setup_signals(self):
        """Configura señales para shutdown graceful."""
        try:
            # Solo configurar signals en el hilo principal
            import threading
            if threading.current_thread() is threading.main_thread():
                def signal_handler(signum, frame):
                    logger.info(f"Signal {signum} received, stopping...")
                    self.running = False
                
                signal.signal(signal.SIGTERM, signal_handler)
                signal.signal(signal.SIGINT, signal_handler)
                logger.info("Signal handlers configured")
            else:
                logger.info("Running in non-main thread, skipping signal setup")
        except Exception as e:
            logger.warning(f"Could not setup signal handlers: {e}")
    
    async def start(self):
        """Inicia el consumer."""
        try:
            logger.info(f"Starting consumer for queue: {self.worker_name}")
            
            self.setup_signals()
            self.running = True
            
            self.worker = Worker(
                self.worker_name,
                self.process_job,
                {"connection": self.redis_url}
            )
            
            logger.info(f"Consumer started for queue: {self.worker_name}")
            
            # Mantener corriendo hasta recibir señal de stop
            while self.running:
                await asyncio.sleep(1)
                
        except Exception as e:
            logger.error(f"Error starting consumer: {str(e)}")
            raise
        finally:
            await self.stop()
    
    async def stop(self):
        """Detiene el consumer."""
        if self.worker:
            logger.info("Stopping consumer...")
            await self.worker.close()
            logger.info("Consumer stopped")

# Función de uso simplificado
def consumer_bullmq(worker: str, function_process):
    """
    Función simplificada para crear y ejecutar un consumer.
    
    Args:
        worker: Nombre de la cola de trabajos
        function_process: Función que procesará los mensajes
    """
    async def run():
        consumer = ConsumerBullMQ(worker, function_process)
        await consumer.start()
    
    try:
        asyncio.run(run())
    except KeyboardInterrupt:
        logger.info("Shutdown completed")

# Ejemplo de uso con executor_function
if __name__ == "__main__":
    from executor import executor_function
    
    # Usar el consumer simplificado
    consumer_bullmq(worker="calibration", function_process=executor_function)