"""
LibreOffice locking mechanism for concurrent worker safety.

LibreOffice doesn't handle concurrent calls well - running multiple soffice
processes simultaneously can cause crashes or corruption. This module provides
a blocking file lock to serialize LibreOffice operations across worker processes.

Usage:
    with libreoffice_lock():
        # LibreOffice operations here
        subprocess.run(['libreoffice', '--headless', ...])
"""

import fcntl
import os
import tempfile
from contextlib import contextmanager

import structlog

logger = structlog.get_logger(__name__)

# Global lock file path - shared across all worker processes
LOCK_FILE_PATH = os.path.join(tempfile.gettempdir(), "dsol_libreoffice.lock")


@contextmanager
def libreoffice_lock(timeout: float | None = None):
    """
    Acquire a blocking file lock for LibreOffice operations.

    This ensures only one LibreOffice process runs at a time across all
    Celery worker processes on the same machine.

    Args:
        timeout: Optional timeout in seconds (not currently used, lock is blocking)

    Yields:
        None when lock is acquired

    Example:
        with libreoffice_lock():
            result = subprocess.run(['libreoffice', '--headless', ...])
    """
    lock_file = None
    try:
        # Open/create the lock file
        lock_file = open(LOCK_FILE_PATH, 'w')

        logger.debug("libreoffice_lock_waiting", lock_file=LOCK_FILE_PATH)

        # Acquire exclusive lock (blocking)
        fcntl.flock(lock_file.fileno(), fcntl.LOCK_EX)

        logger.debug("libreoffice_lock_acquired")

        yield

    finally:
        if lock_file:
            # Release lock
            fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
            lock_file.close()
            logger.debug("libreoffice_lock_released")
