import logging
import json
from logging.handlers import RotatingFileHandler
from pathlib import Path
from datetime import datetime

class JsonFormatter(logging.Formatter):
    """
    Custom JSON log formatter for structured logging.
    Outputs rich JSON objects with context for programmatic parsing and analysis.
    """
    def format(self, record: logging.LogRecord) -> str:
        log_object = {
            "timestamp": datetime.utcfromtimestamp(record.created).strftime("%Y-%m-%dT%H:%M:%SZ"),
            "level": record.levelname,
            "message": record.getMessage(),
            "module": record.module,
            "function": record.funcName,
            "line": record.lineno,
        }

        # Include any extra fields added via logger.info("msg", extra={...})
        # This allows passing structured context: logger.info("msg", extra={"file": "video.mkv", "size": 1024})
        if hasattr(record, "extra") and isinstance(record.extra, dict):
            log_object.update(record.extra)

        # Include exception info if present (for error tracking)
        if record.exc_info:
            log_object["exception"] = self.formatException(record.exc_info)

        return json.dumps(log_object, ensure_ascii=False)

def setup_logger(log_folder: Path, log_file_name: str = "conversion.log", level=logging.INFO) -> logging.Logger:
    """
    Setup logger with structured JSON file output and disabled console output.
    
    Output:
    - File (logs/conversion.log): JSON format with full context for programmatic parsing
    - Console: Disabled (all user output handled via print() for clean terminal UI)
    
    Usage:
        logger.info("Processing complete", extra={
            "file": "video.mkv",
            "size_mb": 1024,
            "duration_sec": 3600
        })
    """
    log_folder.mkdir(parents=True, exist_ok=True)
    log_file = log_folder / log_file_name

    logger = logging.getLogger("conversion_logger")
    logger.setLevel(level)
    logger.propagate = False  # Prevent double logging

    # Formatters
    text_formatter = logging.Formatter(
        "%(asctime)s [%(levelname)s] %(message)s (%(module)s:%(lineno)d)",
        datefmt="%Y-%m-%d %H:%M:%S"
    )
    json_formatter = JsonFormatter()

    # Console handler (disabled - use print() for user-facing output)
    # This prevents duplicate/ugly output mixing with terminal UI
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(text_formatter)
    console_handler.setLevel(logging.CRITICAL + 1)  # Effectively disable (above CRITICAL)

    # File handler (JSON logs)
    file_handler = RotatingFileHandler(log_file, maxBytes=5 * 1024 * 1024, backupCount=3, encoding="utf-8")
    file_handler.setFormatter(json_formatter)
    file_handler.setLevel(level)

    # Add handlers only once
    if not logger.handlers:
        logger.addHandler(console_handler)
        logger.addHandler(file_handler)

    return logger


def setup_failure_logger(log_folder: Path) -> logging.Logger:
    """
    Setup dedicated failure logger for encoding/processing failures.
    
    Output:
    - File (logs/failure.log): Simple text format with timestamp and failure message
    - Use this for tracking files that failed processing for later analysis
    
    Usage:
        failure_logger.warning(f"{file.name} | CQ mode failed: size threshold not met (95%)")
    """
    log_folder.mkdir(parents=True, exist_ok=True)
    log_file = log_folder / "failure.log"
    
    logger = logging.getLogger("failure_logger")
    logger.setLevel(logging.WARNING)
    
    # Prevent duplicate handlers
    if logger.handlers:
        return logger
    
    # Simple text formatter for failure log
    formatter = logging.Formatter(
        "%(asctime)s | %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S"
    )
    
    # File handler only
    file_handler = RotatingFileHandler(log_file, maxBytes=5 * 1024 * 1024, backupCount=3, encoding="utf-8")
    file_handler.setFormatter(formatter)
    file_handler.setLevel(logging.WARNING)
    
    logger.addHandler(file_handler)
    logger.propagate = False
    
    return logger


def log_event(logger: logging.Logger, level: str, message: str, **context):
    """
    Log a structured event with context fields.
    
    Args:
        logger: Logger instance
        level: Log level ("debug", "info", "warning", "error")
        message: Main message text
        **context: Additional context fields (file, size, duration, etc)
    
    Example:
        log_event(logger, "info", "Encoding complete", 
                  file="video.mkv", size_mb=1024, method="CQ", reduction_pct=45)
    """
    log_func = getattr(logger, level.lower(), logger.info)
    log_func(message, extra=context)
