"""واجهة الموديولات (Detector API) — كل موديول يستورد Detector/Detection فقط.

الموديول لا يفتح شبكة/ملفات بنفسه؛ كل وصول للكاميرا/النموذج/VLM عبر Context (أمان).
"""
from __future__ import annotations

from dataclasses import dataclass
from typing import List, Optional


@dataclass
class Detection:
    """نتيجة موديول. flagged=True فقط عند مخالفة تستحق تنبيهاً."""
    flagged: bool
    score: float = 0.0
    note: str = ""
    label: str = ""
    snapshot: Optional[bytes] = None   # صورة الدليل (وإلا يلتقطها المحرك)


class Context:
    """يوفّرها المحرك لكل موديول. الوصول للكاميرا/النموذج/VLM عبرها فقط."""

    def __init__(self, config: dict, model_path: Optional[str], services,
                 camera: Optional[str] = None):
        self.config = config or {}
        self.model_path = model_path
        self.camera = camera
        self._s = services

    def snapshot(self, camera: str) -> Optional[bytes]:
        return self._s.frame(camera)

    def burst(self, camera: str, n: int = 4, gap: float = 0.4) -> List[bytes]:
        return self._s.burst(camera, n, gap)

    def onnx(self, model_path: Optional[str] = None):
        """OnnxDetector مشترك (كسول، مُخزَّن) — الأصناف تُقرأ من ONNX metadata."""
        return self._s.onnx(model_path or self.model_path)

    def vlm(self, feature_key: str, frames: List[bytes]) -> dict:
        """تحليل سحابي (نموذج مدرب / LM Studio / Ollama / Claude)."""
        return self._s.vlm(feature_key, frames, self.camera)

    def log(self, msg: str) -> None:
        self._s.log(msg)


class Detector:
    """صنف أساس لكل موديول. عرّف key، اختر triggers، ونفّذ on_event أو on_frame."""
    key: str = ""
    kind: str = "custom"                # rule | edge_model | vlm | custom
    triggers: List[str] = ["motion"]    # motion|object:<label>|zone:<name>|schedule|stream
    interval_s: int = 0                 # لـ schedule
    fps: float = 2.0                    # لـ stream
    always_run: bool = False            # كواشف ذات حالة (خمول/مركّب): تُستدعى دائماً لا تُهدّأ
    conditions: List[str] = []          # للتنبيه المركّب: مفاتيح الشروط المطلوب تحققها

    def setup(self, ctx: Context) -> None:
        """مرة واحدة عند التحميل (تحميل نموذج كسول)."""

    def on_event(self, ev: dict, ctx: Context) -> Optional[Detection]:
        """الوضع الحدثي (MQTT): ev = {camera, trigger, label?, zones?}."""
        return None

    def on_frame(self, frame: bytes, ctx: Context) -> Optional[Detection]:
        """الوضع البثّي (stream): إطار JPEG من البث الحي."""
        return None
