"""نماذج بوابة الأجهزة — تُطابق مخطط لوحة Beyond Senses (Supabase Postgres).

البوابة لا تملك المخطط؛ اللوحة وهجراتها (local-db-version/supabase/migrations)
هي المصدر. هنا نُعرّف فقط الأعمدة التي تحتاجها البوابة من كل جدول —
create_all يبني نسخة SQLite مكافئة للاختبارات فقط.
"""

import re
import secrets
import uuid
from datetime import datetime, timezone

from sqlalchemy import (JSON, Boolean, DateTime, Float, ForeignKey, Integer,
                        String, Text, Uuid)
from sqlalchemy.orm import Mapped, mapped_column, relationship

from .db import Base


def utcnow():
    return datetime.now(timezone.utc)


def new_token() -> str:
    return secrets.token_hex(32)


class Organization(Base):
    """العميل (tenant) في اللوحة — organizations.active هو مفتاح إيقاف السداد."""

    __tablename__ = "organizations"

    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    name: Mapped[str] = mapped_column(Text)
    active: Mapped[bool] = mapped_column(Boolean, default=True)

    branches: Mapped[list["Branch"]] = relationship(back_populates="organization")


class Branch(Base):
    __tablename__ = "branches"

    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    organization_id: Mapped[uuid.UUID | None] = mapped_column(
        ForeignKey("organizations.id"), nullable=True)
    name: Mapped[str] = mapped_column(Text)
    active: Mapped[bool] = mapped_column(Boolean, default=True)
    # حقول الجهاز (هجرة 20260704120000_veedon_edge_devices)
    device_token: Mapped[str | None] = mapped_column(Text, unique=True, default=new_token)
    config_version: Mapped[int] = mapped_column(Integer, default=1)
    last_seen: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    agent_info: Mapped[dict] = mapped_column(JSON, default=dict)
    alert_numbers: Mapped[str | None] = mapped_column(Text, default="")
    engine_image: Mapped[str | None] = mapped_column(Text, nullable=True)  # OTA لنسخة المحرك
    # حماية الجهاز
    device_status: Mapped[str] = mapped_column(Text, default="pending")
    device_fingerprint: Mapped[str | None] = mapped_column(Text, nullable=True)
    hardware_info: Mapped[dict] = mapped_column(JSON, default=dict)
    is_vm: Mapped[bool] = mapped_column(Boolean, default=False)
    allow_vm: Mapped[bool] = mapped_column(Boolean, default=False)
    device_first_seen: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True)
    sop: Mapped[dict] = mapped_column(JSON, default=dict)  # SOP التصعيد لكل فرع

    organization: Mapped[Organization | None] = relationship(back_populates="branches")
    cameras: Mapped[list["Camera"]] = relationship(back_populates="branch")

    @property
    def is_suspended(self) -> bool:
        if not self.active:
            return True
        return bool(self.organization) and not self.organization.active


class Camera(Base):
    __tablename__ = "cameras"

    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    branch_id: Mapped[uuid.UUID | None] = mapped_column(
        ForeignKey("branches.id"), nullable=True)
    name: Mapped[str] = mapped_column(Text)
    rtsp_url: Mapped[str | None] = mapped_column(Text, nullable=True)
    enabled: Mapped[bool] = mapped_column(Boolean, default=True)
    frigate_identifier: Mapped[str | None] = mapped_column(Text, nullable=True)

    branch: Mapped[Branch | None] = relationship(back_populates="cameras")
    assignments: Mapped[list["CameraEventAssignment"]] = relationship(
        back_populates="camera")

    @property
    def frigate_name(self) -> str:
        """اسم داخلي ثابت للمحرك: frigate_identifier أو slug أو cam_<id>."""
        if self.frigate_identifier:
            return self.frigate_identifier
        slug = re.sub(r"[^a-z0-9_]", "", self.name.lower().replace(" ", "_"))
        return slug or f"cam_{self.id.hex[:8]}"


class EventType(Base):
    """كتالوج المزايا — صفوف feature_key منها هي مزايا Veedon."""

    __tablename__ = "event_types"

    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    name_ar: Mapped[str] = mapped_column(Text)
    name_en: Mapped[str] = mapped_column(Text, default="")
    feature_key: Mapped[str | None] = mapped_column(Text, unique=True, nullable=True)
    kind: Mapped[str] = mapped_column(Text, default="rule")  # rule/vlm/edge_model/engine
    sector: Mapped[str] = mapped_column(Text, default="general")  # general/restaurant/factory/education/health/farm
    default_config: Mapped[dict] = mapped_column(JSON, default=dict)
    available: Mapped[bool] = mapped_column(Boolean, default=True)
    enabled: Mapped[bool] = mapped_column(Boolean, default=True)


class CameraEventAssignment(Base):
    """تفعيل ميزة على كاميرا محددة — جدول اللوحة القائم + عمود config."""

    __tablename__ = "camera_event_assignments"

    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    camera_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("cameras.id"))
    event_type_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("event_types.id"))
    enabled: Mapped[bool] = mapped_column(Boolean, default=True)
    confidence_threshold: Mapped[float | None] = mapped_column(Float, nullable=True)
    config: Mapped[dict] = mapped_column(JSON, default=dict)

    camera: Mapped[Camera] = relationship(back_populates="assignments")
    event_type: Mapped[EventType] = relationship()


class Event(Base):
    __tablename__ = "events"

    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    camera_id: Mapped[uuid.UUID | None] = mapped_column(
        ForeignKey("cameras.id"), nullable=True)
    event_type: Mapped[str] = mapped_column(Text)
    severity: Mapped[str] = mapped_column(Text, default="medium")
    detected_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), default=utcnow)
    meta: Mapped[dict] = mapped_column("metadata", JSON, default=dict)
    reviewed: Mapped[bool] = mapped_column(Boolean, default=False)
    snapshot_url: Mapped[str | None] = mapped_column(Text, nullable=True)


class ReidEmbedding(Base):
    """متجه مظهر شخص (OSNet 512-بُعد، مطبَّع L2) لإعادة التعرّف عبر كاميرات الفرع."""

    __tablename__ = "reid_embeddings"

    id: Mapped[uuid.UUID] = mapped_column(Uuid, primary_key=True, default=uuid.uuid4)
    event_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, nullable=True)
    branch_id: Mapped[uuid.UUID | None] = mapped_column(Uuid, nullable=True)
    camera: Mapped[str] = mapped_column(Text, default="")
    detected_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), default=utcnow)
    embedding: Mapped[list] = mapped_column(JSON, default=list)


FEATURE_CATALOG = [  # (feature_key, name_ar, kind, sector, default_config, available)
    ("restricted_zone", "منطقة ممنوعة", "rule", "general",
     {"coordinates": "", "cooldown_s": 300}, True),
    ("crowding", "تكدس / ازدحام", "rule", "general",
     {"threshold": 6, "cooldown_s": 600}, True),
    ("queue_count", "عدد المنتظرين في الطابور", "rule", "general",
     {"coordinates": "", "interval_min": 10}, True),
    ("camera_health", "مراقبة صحة الكاميرات", "rule", "general", {}, True),
    ("entry_exit_count", "عدّ الدخول والخروج", "rule", "general",
     {"camera": "", "coordinates": "", "interval_min": 15}, True),
    # مزايا 2026 (VDE) — تُستضاف في المحرك المعياري لا في منطق الوكيل التقليدي
    ("inactivity", "كشف الخمول (غياب نشاط)", "rule", "general",
     {"inactive_s": 300, "check_s": 30, "cooldown_s": 600}, True),
    ("vehicle_crossing", "عبور/دخول مركبة لمنطقة", "rule", "general",
     {"coordinates": "", "cooldown_s": 60}, True),
    ("compound_alert", "تنبيه مركّب (عدة شروط)", "rule", "general",
     {"conditions": [], "window_s": 30, "cooldown_s": 60}, True),
    ("ai_deterrence", "الردع الصوتي الذكي", "vlm", "general",
     {"frames": 3, "cooldown_s": 120}, True),
    ("reid", "تتبّع الشخص عبر الكاميرات (re-ID)", "engine", "general",
     {"threshold": 0.5, "window_min": 30}, True),
    ("custom_vlm", "كشف مخصّص بالكلمات (VLM)", "vlm", "general",
     {"prompt": "", "frames": 3, "cooldown_s": 120}, True),
    ("privacy_redaction", "تعتيم الوجوه/الأشخاص في الأدلة (PDPL)", "engine", "general",
     {"mode": "persons"}, True),      # persons | faces — يُعتّم اللقطة قبل التخزين
    ("tailgating", "دخول تطفّلي (أكثر من شخص ببوابة)", "rule", "general",
     {"coordinates": "", "threshold": 2, "cooldown_s": 60}, True),  # كثافة على بوابة
    ("audio_event", "حدث صوتي (صراخ/زجاج/طلق)", "rule", "general",
     {"alert_labels": ["scream", "yell", "glass_break", "gunshot", "fire_alarm"],
      "cooldown_s": 30}, True),   # يُوقظه صوت المحرك؛ دليل تصعيد + شرط مركّب
    ("table_cleanliness", "نظافة الطاولات (AI Vision)", "vlm", "restaurant",
     {"interval_min": 60}, True),
    ("poultry_health", "مؤشرات صحة الدواجن (AI Vision)", "vlm", "farm",
     {"interval_min": 30}, True),
    # وحدات محرك Frigate — تُرندر في config الجهاز (kind=engine)
    ("face_recognition", "التعرف على الوجوه", "engine", "general", {}, True),
    ("lpr", "قراءة لوحات المركبات", "engine", "general", {}, True),
    ("semantic_search", "البحث الدلالي بالوصف", "engine", "general", {}, True),
    ("birdseye", "عين الطائر (كل الكاميرات)", "engine", "general", {"mode": "objects"}, True),
    ("recording", "التسجيل المستمر", "engine", "general", {"retain_days": 7}, True),
    ("audio_detection", "كشف الأصوات", "engine", "general",
     {"labels": ["scream", "yell", "fire_alarm", "glass"]}, True),
    ("motion_mask", "قناع الحركة (تجاهل مناطق)", "engine", "general", {"coordinates": ""}, True),
    ("genai", "الوصف الذكي للأحداث (GenAI)", "engine", "general", {}, False),
    ("smoking", "كشف التدخين", "edge_model", "restaurant",
     {"model": "veedon-smoke-v1", "detect_labels": ["cigarette"]}, True),  # HEIher/smoking MIT
    ("phone_usage", "استخدام الجوال أثناء العمل", "edge_model", "restaurant",
     {"model": "veedon-detect-v1.onnx", "detect_labels": ["cell phone"]}, True),  # COCO عام
    ("uniform_ppe", "الزي / القفازات / غطاء الشعر", "edge_model", "restaurant",
     {"model": "veedon-ppe-v1"}, False),
    # 🏭 المصانع (HCIS/SFDA)
    ("forklift_proximity", "تقارب الرافعات الشوكية بالعمّال", "edge_model", "factory",
     {"model": "veedon-forklift-v1", "min_distance_m": 2}, False),
    ("ppe_industrial", "معدات الحماية الصناعية", "edge_model", "factory",
     {"model": "veedon-ppe-ind-v1", "require": ["hardhat", "vest"]}, False),
    ("ergonomic_posture", "وضعيات العمل الخاطئة", "edge_model", "factory",
     {"model": "veedon-pose-v1"}, False),
    ("machine_zone_intrusion", "دخول منطقة آلة خطرة", "rule", "factory",
     {"coordinates": "", "cooldown_s": 120}, True),
    # 🏫 التعليم (وزارة التعليم) — بلا تعرّف على وجوه
    ("weapon_detection", "كشف الأسلحة والأدوات الحادة", "edge_model", "education",
     {"model": "veedon-weapon-v1"}, False),
    ("fight_detection", "كشف المشاجرات", "vlm", "education", {"interval_min": 0}, True),
    ("bullying", "كشف التنمّر", "vlm", "education", {"interval_min": 0}, True),
    ("stair_fall", "السقوط على السلالم", "vlm", "education", {"interval_min": 0}, True),
    ("student_sleeping", "نوم الطلبة في الفصل", "vlm", "education", {"interval_min": 10}, True),
    ("after_hours_intrusion", "تسكّع/اقتحام خارج الدوام", "rule", "education",
     {"coordinates": "", "cooldown_s": 300}, True),
    ("gate_attendance", "عدّ الحضور عند البوابة", "rule", "education",
     {"coordinates": "", "interval_min": 15}, True),
    # 🏥 الصحة (وزارة الصحة/CBAHI) — معالجة على الجهاز، بلا وجوه
    ("patient_fall", "سقوط المريض / مغادرة السرير", "edge_model", "health",
     {"model": "veedon-fall-v1"}, False),
    ("elopement", "هروب المريض من منطقة", "rule", "health",
     {"coordinates": "", "cooldown_s": 60}, True),
    ("hand_hygiene", "الالتزام بنظافة اليدين", "edge_model", "health",
     {"model": "veedon-hygiene-v1"}, False),
    ("aggression_staff", "العنف/العدوانية ضد الطواقم", "vlm", "health", {"interval_min": 0}, True),
    # 🏨 الفنادق (وزارة السياحة + البلدية)
    ("slip_wet_floor", "أرضية مبتلة / انسكاب", "vlm", "hotel", {"interval_min": 20}, True),
    ("pool_safety", "سلامة منطقة المسبح", "vlm", "hotel", {"interval_min": 5}, True),
    ("luggage_unattended", "حقيبة/غرض متروك", "vlm", "hotel", {"interval_min": 10}, True),
    ("perimeter_intrusion", "اقتحام محيط/مناطق الموظفين", "rule", "hotel",
     {"coordinates": "", "cooldown_s": 120}, True),
    # 🏫 التعليم — مزايا جديدة
    ("vape_detection", "كشف الفيب/الأبخرة", "edge_model", "education",
     {"model": "veedon-vape-v1"}, False),
    ("emergency_lockdown", "تفعيل الإغلاق الطارئ", "rule", "education",
     {"trigger_on": ["weapon_detection"], "cooldown_s": 0}, True),
    ("visitor_unknown", "زائر غير مصرّح", "vlm", "education", {"interval_min": 5}, True),
    ("wrong_direction", "اتجاه معاكس/تسلل", "rule", "education",
     {"coordinates": "", "cooldown_s": 60}, True),
    # 🏭 المصانع — مزايا جديدة
    ("defect_inspection", "فحص جودة المنتج (عيوب)", "edge_model", "factory",
     {"model": "veedon-defect-v1"}, False),
    ("spill_leak", "انسكاب/تسرب", "vlm", "factory", {"interval_min": 10}, True),
    ("thermal_fire", "حرارة/دخان/حريق", "vlm", "factory", {"interval_min": 3}, True),
    ("machine_idle", "توقف خط الإنتاج", "rule", "factory",
     {"coordinates": "", "interval_min": 10}, True),
    # 🕌 المساجد والفعاليات (قطاع جديد)
    ("crowd_density", "كثافة الحشود / خطر التدافع", "rule", "mosque",
     {"camera": "", "coordinates": "", "threshold": 30, "cooldown_s": 30}, True),
    ("crowd_flow", "اتجاه وتدفق الحشود", "rule", "mosque",
     {"camera": "", "coordinates": "", "interval_min": 2}, True),
    ("fallen_person", "شخص ساقط وسط الزحام", "edge_model", "mosque",
     {"model": "veedon-fall-crowd-v1"}, False),
    ("lost_child", "طفل تائه", "vlm", "mosque", {"interval_min": 5}, True),
    ("prayer_occupancy", "إشغال قاعة الصلاة", "rule", "mosque",
     {"camera": "", "coordinates": "", "interval_min": 5}, True),
    # 📦 المستودعات واللوجستيات (قطاع جديد)
    ("loading_dock", "نشاط رصيف التحميل", "rule", "warehouse",
     {"camera": "", "coordinates": "", "interval_min": 10}, True),
    ("package_damage", "تلف الطرود", "vlm", "warehouse", {"interval_min": 10}, True),
    ("suspended_load", "المشي تحت حمل معلّق", "rule", "warehouse",
     {"coordinates": "", "cooldown_s": 60}, True),
    ("pallet_count", "عدّ المنصات (Pallets)", "vlm", "warehouse", {"interval_min": 30}, True),
    # 🛒 التجزئة/السوبرماركت
    ("shelf_out_of_stock", "رفوف فارغة / نفاد", "vlm", "retail", {"interval_min": 30}, True),
    ("planogram_compliance", "التزام ترتيب العرض", "vlm", "retail", {"interval_min": 60}, True),
    ("concealment_theft", "إخفاء منتج / اشتباه سرقة", "edge_model", "retail",
     {"model": "veedon-conceal-v1"}, False),
    ("self_checkout_fraud", "احتيال الدفع الذاتي", "rule", "retail",
     {"camera": "", "pos_integration": True, "cooldown_s": 60}, True),
    # 🐔 المزارع/الدواجن
    ("dead_bird_detection", "كشف الطيور النافقة", "edge_model", "farm",
     {"model": "veedon-deadbird-v1"}, False),
    ("bird_count", "عدّ الطيور", "vlm", "farm", {"interval_min": 60}, True),
    ("uneven_growth", "نمو غير متجانس", "vlm", "farm", {"interval_min": 120}, True),
    # 🏥 الصحة — تشغيلية
    ("patient_wait_time", "زمن انتظار المرضى", "rule", "health",
     {"camera": "", "coordinates": "", "interval_min": 10}, True),
    ("bed_occupancy", "إشغال الأسرّة/المناطق", "rule", "health",
     {"camera": "", "coordinates": "", "interval_min": 15}, True),
    # 🧸 مناطق ألعاب الأطفال (البلدية + هيئة الترفيه)
    ("child_unattended", "طفل بلا مرافق", "vlm", "kids", {"interval_min": 3}, True),
    ("child_fall", "سقوط طفل", "edge_model", "kids",
     {"model": "veedon-childfall-v1"}, False),
    ("child_elopement", "خروج طفل من المنطقة", "rule", "kids",
     {"coordinates": "", "cooldown_s": 30}, True),
    ("play_area_capacity", "تكدس منطقة اللعب", "rule", "kids",
     {"camera": "", "coordinates": "", "threshold": 15, "cooldown_s": 120}, True),
    ("rough_play", "لعب عنيف / خطِر", "vlm", "kids", {"interval_min": 2}, True),
    # ⚽ الملاعب والمنشآت الرياضية (وزارة الرياضة + الدفاع المدني)
    ("pitch_invasion", "اقتحام أرض الملعب", "rule", "sports",
     {"camera": "", "coordinates": "", "cooldown_s": 30}, True),
    ("flare_smoke", "شعلة/دخان/ألعاب نارية", "vlm", "sports", {"interval_min": 1}, True),
    ("fan_violence", "عنف الجماهير", "vlm", "sports", {"interval_min": 1}, True),
    ("masked_person", "شخص ملثّم", "edge_model", "sports",
     {"model": "veedon-mask-v1"}, False),
    ("stand_occupancy", "إشغال المدرجات / كثافة حرجة", "rule", "sports",
     {"camera": "", "coordinates": "", "threshold": 40, "cooldown_s": 30}, True),
]


def seed(db):
    """كتالوج المزايا — على PG تتكفل الهجرة؛ هذا للاختبارات وأي نقص."""
    for key, name_ar, kind, sector, cfg, available in FEATURE_CATALOG:
        if not db.query(EventType).filter_by(feature_key=key).first():
            db.add(EventType(feature_key=key, name_ar=name_ar, name_en=key,
                             kind=kind, sector=sector, default_config=cfg,
                             available=available))
    db.commit()
