"""
yolo_api.py — YOLO detection interface with fallback stubs
"""
import sys
import os
from Core.config_loader import load_config
from Core.env_loader import PROJECT_ROOT

YOLO_AVAILABLE = False

# Fallback stubs
def _stub_sees(c, **kw):         return False
def _stub_count(c):              return 0
def _stub_closest(c="person"):   return None
def _stub_summary():             return "YOLO not loaded"
def _stub_ppe():                 return []
def _stub_too_close(**k):        return False
def _stub_all():                 return set()
def _stub_fps():                 return 0.0
def _stub_pause():               return None
def _stub_resume():              return None

yolo_sees            = _stub_sees
yolo_count           = _stub_count
yolo_closest         = _stub_closest
yolo_summary         = _stub_summary
yolo_ppe_violations  = _stub_ppe
yolo_person_too_close = _stub_too_close
yolo_all_classes     = _stub_all
yolo_fps             = _stub_fps
yolo_pause           = _stub_pause
yolo_resume          = _stub_resume


def init_yolo(raw_frame_ref, frame_lock) -> bool:
    """Start YOLO inference. Returns True if successful."""
    global YOLO_AVAILABLE
    global yolo_sees, yolo_count, yolo_closest, yolo_summary
    global yolo_ppe_violations, yolo_person_too_close, yolo_all_classes, yolo_fps
    global yolo_pause, yolo_resume

    # marcus_yolo.py lives in Vision/
    models_dir = os.path.join(PROJECT_ROOT, "Vision")
    if models_dir not in sys.path:
        sys.path.insert(0, models_dir)

    try:
        from marcus_yolo import (
            start_yolo, yolo_sees as _ys, yolo_count as _yc, yolo_closest as _ycl,
            yolo_summary as _ysu, yolo_ppe_violations as _ypp,
            yolo_person_too_close as _yptc, yolo_all_classes as _yac, yolo_fps as _yfps,
            yolo_pause as _ypause, yolo_resume as _yresume,
        )
    except ImportError as e:
        print(f"marcus_yolo.py not found ({e})")
        return False

    # GPU is required. _resolve_device() raises RuntimeError when CUDA is
    # missing — surface that with an actionable banner before re-raising so
    # Marcus hard-fails with a clear error instead of a raw stack trace.
    try:
        ok = start_yolo(raw_frame_ref=raw_frame_ref, frame_lock=frame_lock)
    except RuntimeError as e:
        print()
        print("╔" + "═" * 68 + "╗")
        print("║  MARCUS STARTUP ABORTED — GPU REQUIRED".ljust(69) + "║")
        print("╠" + "═" * 68 + "╣")
        print(f"║  {str(e)[:66]:<66}  ║")
        print("║" + " " * 68 + "║")
        print("║  On the Jetson, verify:".ljust(69) + "║")
        print("║    tegrastats           # GPU exists & is not throttled".ljust(69) + "║")
        print("║    python3 -c 'import torch; print(torch.cuda.is_available())'".ljust(69) + "║")
        print("║    nvcc --version       # CUDA toolkit reachable".ljust(69) + "║")
        print("║  Expected: torch 2.1.0 nv23.06, CUDA 11.4, GPU=Orin.".ljust(69) + "║")
        print("║  See Doc/environment.md section 9 for the reinstall recipe.".ljust(69) + "║")
        print("╚" + "═" * 68 + "╝")
        print()
        raise

    if ok:
        YOLO_AVAILABLE       = True
        yolo_sees            = _ys
        yolo_count           = _yc
        yolo_closest         = _ycl
        yolo_summary         = _ysu
        yolo_ppe_violations  = _ypp
        yolo_person_too_close = _yptc
        yolo_all_classes     = _yac
        yolo_fps             = _yfps
        yolo_pause           = _ypause
        yolo_resume          = _yresume
    print(f"YOLO {'started' if ok else 'failed to start'}")
    return ok
