"""
Auto-Label Scheduler

Background scheduler for processing documents pending auto-labeling.
"""

import logging
import threading
from pathlib import Path

from backend.data.repositories import DocumentRepository, AnnotationRepository
from backend.web.core.task_interface import TaskRunner, TaskStatus
from backend.web.services.db_autolabel import (
    get_pending_autolabel_documents,
    process_document_autolabel,
)
from backend.web.services.storage_helpers import get_storage_helper

logger = logging.getLogger(__name__)


class AutoLabelScheduler(TaskRunner):
    """Scheduler for auto-labeling tasks."""

    def __init__(
        self,
        check_interval_seconds: int = 10,
        batch_size: int = 5,
        output_dir: Path | None = None,
    ):
        """
        Initialize auto-label scheduler.

        Args:
            check_interval_seconds: Interval to check for pending tasks
            batch_size: Number of documents to process per batch
            output_dir: Output directory for temporary files
        """
        self._check_interval = check_interval_seconds
        self._batch_size = batch_size

        # Get output directory from StorageHelper
        if output_dir is None:
            storage = get_storage_helper()
            output_dir = storage.get_autolabel_output_path()
        self._output_dir = output_dir or Path("data/autolabel_output")

        self._running = False
        self._thread: threading.Thread | None = None
        self._stop_event = threading.Event()
        self._lock = threading.Lock()
        self._doc_repo = DocumentRepository()
        self._ann_repo = AnnotationRepository()

    @property
    def name(self) -> str:
        """Unique identifier for this runner."""
        return "autolabel_scheduler"

    @property
    def is_running(self) -> bool:
        """Check if scheduler is running."""
        return self._running

    def get_status(self) -> TaskStatus:
        """Get current status of the scheduler."""
        try:
            pending_docs = get_pending_autolabel_documents(limit=1000)
            pending_count = len(pending_docs)
        except Exception:
            pending_count = 0

        return TaskStatus(
            name=self.name,
            is_running=self._running,
            pending_count=pending_count,
            processing_count=1 if self._running else 0,
        )

    def start(self) -> None:
        """Start the scheduler."""
        with self._lock:
            if self._running:
                logger.warning("AutoLabel scheduler already running")
                return

            self._running = True
            self._stop_event.clear()
            self._thread = threading.Thread(target=self._run_loop, daemon=True)
            self._thread.start()
            logger.info("AutoLabel scheduler started")

    def stop(self, timeout: float | None = None) -> None:
        """Stop the scheduler.

        Args:
            timeout: Maximum time to wait for graceful shutdown.
                    If None, uses default of 5 seconds.
        """
        # Minimize lock scope to avoid potential deadlock
        with self._lock:
            if not self._running:
                return

            self._running = False
            self._stop_event.set()
            thread_to_join = self._thread

        effective_timeout = timeout if timeout is not None else 5.0
        if thread_to_join:
            thread_to_join.join(timeout=effective_timeout)

        with self._lock:
            self._thread = None

        logger.info("AutoLabel scheduler stopped")

    def _run_loop(self) -> None:
        """Main scheduler loop."""
        while self._running:
            try:
                self._process_pending_documents()
            except Exception as e:
                logger.error(f"Error in autolabel scheduler loop: {e}", exc_info=True)

            # Wait for next check interval
            self._stop_event.wait(timeout=self._check_interval)

    def _process_pending_documents(self) -> None:
        """Check and process pending auto-label documents."""
        try:
            documents = get_pending_autolabel_documents(limit=self._batch_size)

            if not documents:
                return

            logger.info(f"Processing {len(documents)} pending autolabel documents")

            for doc in documents:
                if self._stop_event.is_set():
                    break

                try:
                    result = process_document_autolabel(
                        document=doc,
                        output_dir=self._output_dir,
                        doc_repo=self._doc_repo,
                        ann_repo=self._ann_repo,
                    )

                    if result.get("success"):
                        logger.info(
                            f"AutoLabel completed for document {doc.document_id}"
                        )
                    else:
                        logger.warning(
                            f"AutoLabel failed for document {doc.document_id}: "
                            f"{result.get('error', 'Unknown error')}"
                        )

                except Exception as e:
                    logger.error(
                        f"Error processing document {doc.document_id}: {e}",
                        exc_info=True,
                    )

        except Exception as e:
            logger.error(f"Error fetching pending documents: {e}", exc_info=True)


# Global scheduler instance
_autolabel_scheduler: AutoLabelScheduler | None = None
_autolabel_lock = threading.Lock()


def get_autolabel_scheduler() -> AutoLabelScheduler:
    """Get the auto-label scheduler instance.

    Uses double-checked locking pattern for thread safety.
    """
    global _autolabel_scheduler

    if _autolabel_scheduler is None:
        with _autolabel_lock:
            if _autolabel_scheduler is None:
                _autolabel_scheduler = AutoLabelScheduler()

    return _autolabel_scheduler


def start_autolabel_scheduler() -> None:
    """Start the global auto-label scheduler."""
    scheduler = get_autolabel_scheduler()
    scheduler.start()


def stop_autolabel_scheduler() -> None:
    """Stop the global auto-label scheduler."""
    global _autolabel_scheduler
    if _autolabel_scheduler:
        _autolabel_scheduler.stop()
        _autolabel_scheduler = None
