"""تحليلات تشغيلية/BI من الفيديو — يحوّل Veedon من «تكلفة أمن» إلى **أداة إيرادات**
(مطاعم/تجزئة). يُجمّع من الأحداث القائمة: footfall + خريطة حرارية زمنية + ذروة الطوابير +
إشغال + اتجاهات — بلا كشف جديد. (أهمّ محور تجاري 2026 — NRF: 73% من كبار التجار).
"""
from collections import defaultdict
from datetime import timedelta

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import select
from sqlalchemy.orm import Session

from .db import get_db
from .models import Branch, Event, utcnow

router = APIRouter(prefix="/api/insights", tags=["analytics"])

# مزايا العدّ التي تحمل عدداً في meta.count (footfall/إشغال)
COUNT_FEATURES = {"entry_exit_count", "queue_count", "gate_attendance", "crowd_flow",
                  "loading_dock", "patient_wait_time", "prayer_occupancy",
                  "bed_occupancy", "stand_occupancy", "play_area_capacity",
                  "crowd_density"}
OCCUPANCY = {"prayer_occupancy", "bed_occupancy", "stand_occupancy",
             "play_area_capacity", "crowd_density"}
DOW_AR = ["الإثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت", "الأحد"]


def compute(db: Session, branch: Branch, days: int) -> dict:
    since = utcnow() - timedelta(days=days)
    cam_ids = [c.id for c in branch.cameras]
    cam_name = {c.id: c.name for c in branch.cameras}
    events = []
    if cam_ids:
        events = db.scalars(select(Event).where(
            Event.camera_id.in_(cam_ids), Event.detected_at >= since)
            .order_by(Event.detected_at.desc()).limit(8000)).all()

    heat = [[0] * 24 for _ in range(7)]        # dow × hour — خريطة حرارية زمنية
    per_cam = defaultdict(int)                 # نشاط لكل كاميرا/منطقة
    per_day = defaultdict(lambda: {"events": 0, "footfall": 0})
    queue_peak = defaultdict(int)
    occ_vals = []
    for e in events:
        dt = e.detected_at
        if not dt:
            continue
        heat[dt.weekday()][dt.hour] += 1
        per_cam[cam_name.get(e.camera_id, "—")] += 1
        d = dt.date().isoformat()
        row = per_day[d]
        row["events"] += 1
        cnt = int((e.meta or {}).get("count", 0) or 0)
        if e.event_type in COUNT_FEATURES and cnt:
            row["footfall"] += cnt
        if e.event_type == "queue_count" and cnt:
            queue_peak[d] = max(queue_peak[d], cnt)
        if e.event_type in OCCUPANCY and cnt:
            occ_vals.append(cnt)

    footfall_by_day = [{"date": d, "footfall": per_day[d]["footfall"],
                        "events": per_day[d]["events"]} for d in sorted(per_day)]
    foot = [x["footfall"] for x in footfall_by_day]
    avg_foot = round(sum(foot) / len(foot), 1) if foot else 0
    today = utcnow().date().isoformat()
    today_foot = per_day.get(today, {}).get("footfall", 0)
    trend = round((today_foot - avg_foot) / avg_foot * 100) if avg_foot else 0

    # ساعة الذروة (أعلى نشاط عبر الأيام)
    by_hour = [sum(heat[dow][h] for dow in range(7)) for h in range(24)]
    peak_hour = max(range(24), key=lambda h: by_hour[h]) if any(by_hour) else 0
    avg_occ = round(sum(occ_vals) / len(occ_vals), 1) if occ_vals else 0
    # تقدير زمن المكوث (قانون ليتل: W ≈ L/λ) — إشغال ÷ معدّل الوصول اليومي
    arrival_rate = avg_foot / 24 if avg_foot else 0    # زوّار/ساعة تقريباً
    dwell_min = round(avg_occ / arrival_rate * 60, 1) if arrival_rate and avg_occ else None

    return {
        "days": days, "total_footfall": sum(foot), "avg_daily_footfall": avg_foot,
        "trend_pct": trend, "peak_hour": peak_hour, "avg_occupancy": avg_occ,
        "dwell_min_est": dwell_min,
        "footfall_by_day": footfall_by_day,
        "heatmap": heat, "dow_labels": DOW_AR,
        "top_zones": sorted(({"zone": k, "activity": v} for k, v in per_cam.items()),
                            key=lambda x: -x["activity"])[:8],
        "queue_peak_by_day": [{"date": d, "peak": queue_peak[d]}
                              for d in sorted(queue_peak)],
    }


@router.get("/analytics/branch/{branch_id}")
def analytics(branch_id: str, days: int = 7, db: Session = Depends(get_db)):
    """تحليلات تشغيلية للفرع: footfall + خريطة حرارية + ذروة + اتجاه + إشغال/مكوث."""
    branch = db.get(Branch, branch_id)
    if not branch:
        raise HTTPException(404, "branch not found")
    return compute(db, branch, days)
