"""Quick helper functions for one-line operations."""

import numpy as np
from typing import Optional, Any, Dict
from eye.detection.core import Detections
from eye.core.tracking import Tracker, TrackerType
from eye.annotators.core import BoxAnnotator, LabelAnnotator

# Module-level tracker cache for stateful multi-frame tracking
_tracker_cache: Dict[str, Tracker] = {}


def _get_cached_tracker(use_case: str) -> Tracker:
    """Return a cached tracker for the given use-case, creating one if needed."""
    if use_case not in _tracker_cache:
        if use_case == "pedestrians":
            _tracker_cache[use_case] = Tracker(TrackerType.BYTETRACK, inflation_factor=1.8)
        elif use_case == "sports":
            _tracker_cache[use_case] = Tracker(TrackerType.BYTETRACK, inflation_factor=2.0)
        else:
            _tracker_cache[use_case] = Tracker(TrackerType.SORT, inflation_factor=1.5)
    return _tracker_cache[use_case]


def detect(model_results: Any, model_type: str = "auto") -> Detections:
    """Convert any model output to Detections (one-liner).

    When *model_type* is ``"auto"`` (the default) the format is detected
    automatically — this handles YOLO, Roboflow, Detectron2, MMDetection,
    TensorFlow, PyTorch, OpenCV, ONNX and more.

    Args:
        model_results: Raw model output from any supported framework.
        model_type: ``"auto"`` (recommended), or an explicit hint:
            ``"yolo"``, ``"roboflow"``, ``"detectron2"``, ``"mmdetection"``,
            ``"tensorflow"``, ``"pytorch"``, ``"opencv"``.

    Returns:
        Detections

    Example:
        >>> detections = eye.detect(yolo_results)          # auto
        >>> detections = eye.detect(rf_results, "roboflow") # explicit
    """
    from eye.detection.auto_convert import (
        auto_convert, from_yolo, from_roboflow, from_detectron2,
        from_mmdetection, from_pytorch, from_tensorflow, from_opencv,
    )

    _DISPATCH = {
        "auto": auto_convert,
        "yolo": from_yolo,
        "roboflow": from_roboflow,
        "detectron2": from_detectron2,
        "mmdetection": from_mmdetection,
        "pytorch": from_pytorch,
        "tensorflow": from_tensorflow,
        "opencv": from_opencv,
    }

    converter = _DISPATCH.get(model_type)
    if converter is None:
        supported = ", ".join(sorted(_DISPATCH.keys()))
        raise ValueError(
            f"Unknown model_type={model_type!r}. Supported: {supported}"
        )
    return converter(model_results)


def track(
    detections: Detections,
    tracker: Optional[Tracker] = None,
    use_case: str = "traffic"
) -> Detections:
    """Track detections (one-liner with auto-setup).
    
    When ``tracker`` is *None*, a cached tracker is created (or reused) for
    the given ``use_case`` so that IDs persist across frames.

    Args:
        detections: Input detections
        tracker: Existing tracker (or None to auto-create/reuse)
        use_case: "traffic", "pedestrians", "sports", etc.
    
    Returns:
        Tracked detections
    
    Example:
        >>> tracked = eye.track(detections, use_case="traffic")
    """
    if tracker is None:
        tracker = _get_cached_tracker(use_case)
    
    return tracker.update(detections)


def annotate(
    image: np.ndarray,
    detections: Detections,
    labels: Optional[list] = None,
    show_boxes: bool = True,
    show_labels: bool = True
) -> np.ndarray:
    """Annotate image (one-liner).
    
    Args:
        image: Input image
        detections: Detections to draw
        labels: Custom labels (or None for auto)
        show_boxes: Draw bounding boxes
        show_labels: Draw labels
    
    Returns:
        Annotated image
    
    Example:
        >>> annotated = eye.annotate(frame, detections)
    """
    result = image.copy()
    
    if show_boxes:
        box_ann = BoxAnnotator()
        result = box_ann.annotate(result, detections)
    
    if show_labels:
        if labels is None and detections.tracker_id is not None:
            labels = [f"#{tid}" for tid in detections.tracker_id]
        elif labels is None and detections.class_id is not None:
            labels = [f"Class {cid}" for cid in detections.class_id]
        
        if labels:
            label_ann = LabelAnnotator()
            result = label_ann.annotate(result, detections, labels)
    
    return result
