#!/usr/bin/env python3
"""
Edge vision agent — runs YOLOv8 nano + custom shelf classifier.
Sends only events (not video) to the POS backend.
"""
import cv2
import json
import time
import hmac
import hashlib
import requests
import numpy as np
from ultralytics import YOLO
from pathlib import Path

BACKEND_URL   = "https://pos.example.com/vision/ingest"
EDGE_SECRET   = "edge-shared-secret"
CAMERA_ID     = 42
ZONE_ID       = 7
POST_INTERVAL = 5   # seconds between event pushes

model = YOLO("yolov8n.pt")
shelf_model = YOLO("models/shelf_oos.pt")   # custom-trained

def sign(body: bytes) -> str:
    return hmac.new(EDGE_SECRET.encode(), body, hashlib.sha256).hexdigest()

def detect_oos(frame):
    """Return list of {product_id, facings_missing, confidence}."""
    results = shelf_model.predict(frame, conf=0.5, verbose=False)
    events = []
    for r in results:
        for box in r.boxes:
            cls = int(box.cls[0])
            conf = float(box.conf[0])
            if cls == 0:  # class 0 = empty shelf slot
                events.append({
                    "type": "shelf.oos",
                    "confidence": conf,
                    "payload": {"product_id": None, "facings_missing": 1}
                })
    return events

def detect_people(frame):
    results = model.predict(frame, classes=[0], conf=0.6, verbose=False)
    count = sum(len(r.boxes) for r in results)
    if count > 0:
        return [{"type": "person.detected", "confidence": 0.9, "payload": {"count": count}}]
    return []

def push(events):
    if not events:
        return
    body = json.dumps({
        "camera_id": CAMERA_ID,
        "zone_id": ZONE_ID,
        "events": events
    }).encode()
    try:
        requests.post(
            BACKEND_URL,
            data=body,
            headers={
                "Content-Type": "application/json",
                "X-Vision-Signature": sign(body),
            },
            timeout=5,
        )
    except Exception as e:
        print(f"push failed: {e}")

def main():
    cap = cv2.VideoCapture("rtsp://user:pass@camera-ip/stream1")
    last_post = 0
    while True:
        ok, frame = cap.read()
        if not ok:
            time.sleep(1)
            continue

        events = []
        events += detect_oos(frame)
        events += detect_people(frame)

        now = time.time()
        if events and now - last_post > POST_INTERVAL:
            push(events)
            last_post = now

        time.sleep(0.1)

if __name__ == "__main__":
    main()