import os
import logging
import requests
import json
import threading
import queue
import time
from typing import Dict, Any, Optional

class LogForwarder:
    """
    Forwards logs to the Node.js API for real-time frontend display
    Uses a background thread to avoid blocking the main thread
    """
    
    def __init__(self, api_url: str = None, api_key: str = None):
        """
        Initialize the log forwarder
        
        Args:
            api_url: URL of the Node.js API logs endpoint
            api_key: Internal API key for authentication
        """
        self.api_url = api_url or os.environ.get("NODEJS_API_URL", "http://localhost:5000/internal-api")
        self.api_key = api_key or os.environ.get("INTERNAL_API_KEY")
        self.log_queue = queue.Queue()
        self.is_running = False
        self.worker_thread = None
        self.logger = logging.getLogger(__name__)
        
        # Start the worker thread
        self.start()
    
    def start(self):
        """Start the worker thread to process logs"""
        if not self.is_running:
            self.is_running = True
            self.worker_thread = threading.Thread(target=self._process_logs, daemon=True)
            self.worker_thread.start()
            self.logger.info("LogForwarder started")
    
    def stop(self):
        """Stop the worker thread"""
        self.is_running = False
        if self.worker_thread:
            self.worker_thread.join(timeout=5)
            self.logger.info("LogForwarder stopped")
    
    def _process_logs(self):
        """Process logs from the queue and send them to the API"""
        while self.is_running:
            try:
                # Get log from queue with timeout to check is_running periodically
                try:
                    log_entry = self.log_queue.get(timeout=1)
                except queue.Empty:
                    continue
                
                # Send log to API
                self._send_log(log_entry)
                
                # Mark task as done
                self.log_queue.task_done()
            except Exception as e:
                self.logger.error(f"Error processing log: {e}")
    
    def _send_log(self, log_entry: Dict[str, Any]):
        """
        Send log to API
        
        Args:
            log_entry: Log entry to send
        """
        try:
            response = requests.post(
                f"{self.api_url}/logs/entry",
                json=log_entry,
                headers={
                    "x-internal-api-key": self.api_key,
                    "Content-Type": "application/json"
                },
                timeout=5
            )
            
            if response.status_code != 200:
                self.logger.warning(f"Failed to send log to API: {response.status_code} {response.text}")
        except Exception as e:
            self.logger.warning(f"Error sending log to API: {e}")
    
    def log(self, tenant_id: str, process_id: str, process_type: str, 
            message: str, level: str = "info", details: Optional[Dict[str, Any]] = None):
        """
        Add log to queue
        
        Args:
            tenant_id: Tenant ID
            process_id: Process ID (tender_id, analysis_id, etc.)
            process_type: Process type (discovery, analysis, bid_generation)
            message: Log message
            level: Log level (debug, info, warning, error)
            details: Additional details
        """
        log_entry = {
            "tenant_id": tenant_id,
            "process_id": process_id,
            "process_type": process_type,
            "message": message,
            "level": level,
            "details": details or {},
            "timestamp": time.strftime("%Y-%m-%dT%H:%M:%S.%fZ", time.gmtime())
        }
        
        self.log_queue.put(log_entry)

# Create a global instance
log_forwarder = LogForwarder()

# Create a custom logging handler that forwards logs to the API
class ApiLogHandler(logging.Handler):
    def __init__(self, tenant_id: str = None, process_id: str = None, process_type: str = None):
        super().__init__()
        self.tenant_id = tenant_id
        self.process_id = process_id
        self.process_type = process_type
    
    def emit(self, record):
        # Skip if we don't have the required identifiers
        if not self.tenant_id or not self.process_id or not self.process_type:
            return
            
        # Get log level
        level = record.levelname.lower()
        
        # Format message
        message = self.format(record)
        
        # Extract details from record
        details = {
            "logger_name": record.name,
            "path": record.pathname,
            "line": record.lineno
        }
        
        # Add exception info if present
        if record.exc_info:
            details["exception"] = str(record.exc_info[1])
            details["traceback"] = self.formatException(record.exc_info)
        
        # Forward log
        log_forwarder.log(
            tenant_id=self.tenant_id,
            process_id=self.process_id,
            process_type=self.process_type,
            message=message,
            level=level,
            details=details
        )

def setup_api_logging(logger_name: str, tenant_id: str, process_id: str, process_type: str):
    """
    Set up API logging for a specific logger
    
    Args:
        logger_name: Logger name
        tenant_id: Tenant ID
        process_id: Process ID
        process_type: Process type
    
    Returns:
        logger: Configured logger
    """
    logger = logging.getLogger(logger_name)
    
    # Create and add the API log handler
    handler = ApiLogHandler(tenant_id, process_id, process_type)
    handler.setLevel(logging.INFO)  # Set minimum level for API logging
    formatter = logging.Formatter('%(message)s')  # Keep it simple, we'll add details in the API
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    
    return logger