"""
patrol.py — Autonomous patrol loop with YOLO PPE detection + LLaVA scene assessment
"""
import time

from API.zmq_api import gradual_stop
from API.camera_api import get_frame
from API.yolo_api import yolo_ppe_violations, yolo_person_too_close, yolo_summary
from API.llava_api import ask_patrol
from API.memory_api import mem, log_detection
from Brain.executor import move_step
from Core.config_loader import load_config

_cfg = load_config("Patrol")

DEFAULT_DURATION   = _cfg["default_duration_minutes"]
PROXIMITY_THRESH   = _cfg["proximity_threshold"]
PROXIMITY_PAUSE    = _cfg["proximity_pause_s"]


def patrol(duration_minutes: float = 0.0, alert_callback=None):
    """
    Timed patrol loop.

    Each iteration:
      1. YOLO PPE violation check  -> log + alert
      2. LLaVA scene assessment    -> decide next move
      3. Proximity safety stop     -> pause if someone is too close
      4. Execute move_step

    Parameters
    ----------
    duration_minutes : float
        How long to patrol (default from config).
    alert_callback : callable, optional
        Called with (alert_text: str) whenever an alert fires.
    """
    if duration_minutes <= 0:
        duration_minutes = DEFAULT_DURATION

    end_time = time.time() + duration_minutes * 60.0
    step = 0

    print(f"  [Patrol] Starting {duration_minutes:.1f}-minute patrol")

    try:
        while time.time() < end_time:
            step += 1

            # ----- 1. YOLO PPE violations -----
            violations = yolo_ppe_violations()
            if violations:
                for v in violations:
                    alert_text = f"PPE violation: {v}"
                    print(f"  [Patrol] {alert_text}")
                    log_detection(v, position="patrol", distance="")
                    if alert_callback:
                        alert_callback(alert_text)

            # ----- 2. LLaVA scene assessment -----
            img_b64 = get_frame()
            if img_b64:
                d = ask_patrol(img_b64)
            else:
                d = {"observation": "no frame", "alert": None,
                     "next_move": "forward", "duration": 1.0}

            observation = d.get("observation", "")
            alert       = d.get("alert")
            next_move   = d.get("next_move", "forward")
            duration    = float(d.get("duration", 1.0))

            if observation:
                print(f"  [Patrol] step {step}: {observation}")

            if alert:
                alert_text = f"Alert: {alert}"
                print(f"  [Patrol] {alert_text}")
                if alert_callback:
                    alert_callback(alert_text)

            # Log interesting detections to memory
            if mem and observation and "person" in observation.lower():
                log_detection("person", position="patrol", distance="")

            # ----- 3. Proximity safety stop (YOLO + LiDAR) -----
            lidar_blocked = False
            try:
                from API.lidar_api import obstacle_ahead
                lidar_blocked = obstacle_ahead()
            except ImportError:
                pass

            if yolo_person_too_close(threshold=PROXIMITY_THRESH) or lidar_blocked:
                reason = "LiDAR obstacle" if lidar_blocked else "Person too close"
                print(f"  [Patrol] {reason} — pausing {PROXIMITY_PAUSE}s")
                gradual_stop()
                time.sleep(PROXIMITY_PAUSE)
                continue

            # ----- 4. Execute movement -----
            if next_move and next_move != "stop":
                move_step(next_move, duration)
            else:
                gradual_stop()
                time.sleep(0.5)

    except KeyboardInterrupt:
        print("  [Patrol] Interrupted")
    finally:
        gradual_stop()

    print(f"  [Patrol] Finished after {step} steps")
    return step
