"""BAN YARO — Admin / Moderator Backend"""
import asyncio
import os
import sys
import time
import platform
from datetime import datetime
from zoneinfo import ZoneInfo

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from typing import Optional
from database import db, DB_PATH
from auth import get_current_user

router = APIRouter()

_TZ         = ZoneInfo("Europe/Berlin")
_start_time = time.time()

# Umami token cache
_umami_token: dict = {"token": None, "expires": 0.0}


async def _umami_auth() -> str:
    global _umami_token
    if _umami_token["token"] and time.time() < _umami_token["expires"]:
        return _umami_token["token"]
    import httpx
    url  = os.getenv("UMAMI_URL", "").rstrip("/")
    resp = await httpx.AsyncClient().post(
        f"{url}/api/auth/login",
        json={"username": os.getenv("UMAMI_USERNAME"), "password": os.getenv("UMAMI_PASSWORD")},
        timeout=10,
    )
    resp.raise_for_status()
    tok = resp.json()["token"]
    _umami_token = {"token": tok, "expires": time.time() + 23 * 3600}
    return tok

# Audit-Tabelle anlegen (einmalig beim Import)
with db() as _conn:
    _conn.executescript("""
        CREATE TABLE IF NOT EXISTS admin_audit (
            id         INTEGER PRIMARY KEY AUTOINCREMENT,
            admin_id   INTEGER NOT NULL,
            admin_name TEXT,
            action     TEXT NOT NULL,
            target     TEXT,
            detail     TEXT,
            created_at TEXT NOT NULL DEFAULT (datetime('now'))
        );
    """)


# ------------------------------------------------------------------
# Helpers
# ------------------------------------------------------------------
def _audit(conn, admin, action: str, target: str = None, detail: str = None):
    """Schreibt einen Audit-Eintrag in die admin_audit-Tabelle."""
    conn.execute(
        "INSERT INTO admin_audit (admin_id, admin_name, action, target, detail) VALUES (?,?,?,?,?)",
        (admin["id"], admin.get("name"), action, target, detail),
    )


# ------------------------------------------------------------------
# Dependency: Moderator oder Admin
# ------------------------------------------------------------------
def require_mod(user=Depends(get_current_user)):
    if user["rolle"] not in ("admin", "moderator") and not user.get("is_moderator"):
        raise HTTPException(403, "Kein Zugriff.")
    return user

def require_admin(user=Depends(get_current_user)):
    if user["rolle"] != "admin":
        raise HTTPException(403, "Nur Admins.")
    return user


# ------------------------------------------------------------------
# Schemas
# ------------------------------------------------------------------
class UserPatch(BaseModel):
    rolle:           Optional[str] = None   # user | moderator | admin
    is_moderator:    Optional[int] = None
    is_banned:       Optional[int] = None
    ban_reason:      Optional[str] = None
    is_social_media: Optional[int] = None

class WikiEnrichBody(BaseModel):
    limit: int = 10

class ThreadAdminPatch(BaseModel):
    is_pinned:  Optional[int] = None
    is_locked:  Optional[int] = None
    is_deleted: Optional[int] = None


# ------------------------------------------------------------------
# GET /api/admin/action-items
# ------------------------------------------------------------------
@router.get("/action-items")
async def action_items(user=Depends(require_mod)):
    with db() as conn:
        jobs = conn.execute(
            "SELECT COUNT(*) FROM job_applications WHERE status IN ('pending','reviewing')"
        ).fetchone()[0]
        breeders = conn.execute(
            "SELECT COUNT(*) FROM users WHERE breeder_status='pending'"
        ).fetchone()[0]
        reports = conn.execute(
            "SELECT COUNT(*) FROM forum_reports WHERE resolved=0"
        ).fetchone()[0]
        fotos = conn.execute(
            "SELECT COUNT(*) FROM wiki_foto_submissions WHERE status='pending'"
        ).fetchone()[0]
        poi_edits = conn.execute(
            "SELECT COUNT(*) FROM osm_poi_edits WHERE status='pending'"
        ).fetchone()[0]
        users_today = conn.execute(
            "SELECT COUNT(*) FROM users WHERE DATE(created_at)=DATE('now')"
        ).fetchone()[0]
    return {
        "jobs_pending":     jobs,
        "breeder_pending":  breeders,
        "reports_open":     reports,
        "fotos_pending":    fotos,
        "poi_edits_pending": poi_edits,
        "users_today":      users_today,
    }


# ------------------------------------------------------------------
# GET /api/admin/stats
# ------------------------------------------------------------------
@router.get("/stats")
async def stats(user=Depends(require_mod)):
    with db() as conn:
        users_total  = conn.execute("SELECT COUNT(*) FROM users").fetchone()[0]
        users_today  = conn.execute(
            "SELECT COUNT(*) FROM users WHERE DATE(created_at)=DATE('now')"
        ).fetchone()[0]
        threads      = conn.execute(
            "SELECT COUNT(*) FROM forum_threads WHERE is_deleted=0"
        ).fetchone()[0]
        posts        = conn.execute(
            "SELECT COUNT(*) FROM forum_posts WHERE is_deleted=0"
        ).fetchone()[0]
        open_reports = conn.execute(
            "SELECT COUNT(*) FROM forum_reports WHERE resolved=0"
        ).fetchone()[0]
        banned       = conn.execute(
            "SELECT COUNT(*) FROM users WHERE is_banned=1"
        ).fetchone()[0]
        dogs_total   = conn.execute("SELECT COUNT(*) FROM dogs").fetchone()[0]
        poison_total = conn.execute(
            "SELECT COUNT(*) FROM poison WHERE geloest=0 AND expires_at > datetime('now')"
        ).fetchone()[0]

        # Erweiterte Metriken
        push_subscriptions = conn.execute(
            "SELECT COUNT(*) FROM push_subscriptions"
        ).fetchone()[0]
        active_users_7d = conn.execute(
            "SELECT COUNT(*) FROM users WHERE last_seen > datetime('now', '-7 days')"
        ).fetchone()[0]
        # Media aus diary (media_url) + health (datei_url)
        media_diary  = conn.execute(
            "SELECT COUNT(*) FROM diary WHERE media_url IS NOT NULL AND media_url != ''"
        ).fetchone()[0]
        media_health = conn.execute(
            "SELECT COUNT(*) FROM health WHERE datei_url IS NOT NULL AND datei_url != ''"
        ).fetchone()[0]
        media_count  = media_diary + media_health
        routes_total = conn.execute("SELECT COUNT(*) FROM routes").fetchone()[0]
        events_total = conn.execute("SELECT COUNT(*) FROM events").fetchone()[0]
        osm_total    = conn.execute("SELECT COUNT(*) FROM osm_pois").fetchone()[0]
        osm_tiles    = conn.execute("SELECT COUNT(*) FROM osm_tiles").fetchone()[0]
        osm_by_type  = {
            row[0]: row[1]
            for row in conn.execute(
                "SELECT type, COUNT(*) FROM osm_pois GROUP BY type ORDER BY 2 DESC"
            ).fetchall()
        }

        # KI-Nutzung
        try:
            from ki import CLOUD_WEEKLY_LIMIT
            ki_today = conn.execute(
                "SELECT COALESCE(SUM(count),0) FROM ki_daily_calls WHERE date=DATE('now')"
            ).fetchone()[0]
            ki_week = conn.execute(
                "SELECT COALESCE(SUM(count),0) FROM ki_daily_calls WHERE date>=DATE('now','-6 days')"
            ).fetchone()[0]
            ki_month = conn.execute(
                "SELECT COALESCE(SUM(count),0) FROM ki_daily_calls WHERE date>=DATE('now','start of month')"
            ).fetchone()[0]
            ki_users_today = conn.execute(
                "SELECT COUNT(DISTINCT user_id) FROM ki_daily_calls WHERE date=DATE('now')"
            ).fetchone()[0]
            # Aufschlüsselung nach Quelle (diese Woche)
            _src_week = {
                r[0]: r[1] for r in conn.execute(
                    "SELECT source, COALESCE(SUM(count),0) FROM ki_daily_calls "
                    "WHERE date>=DATE('now','-6 days') GROUP BY source"
                ).fetchall()
            }
            ki_cloud_week = _src_week.get("cloud", 0)
            ki_local_week = _src_week.get("local", 0)
            ki_luna_week  = _src_week.get("luna", 0)
            # Top-User Cloud diese Woche
            ki_top_users = [
                {"user_id": r[0], "name": r[1], "cloud_calls": r[2]} for r in conn.execute(
                    """SELECT k.user_id, u.name, SUM(k.count) as n
                       FROM ki_daily_calls k JOIN users u ON u.id=k.user_id
                       WHERE k.source='cloud' AND k.date>=DATE('now','-6 days')
                       GROUP BY k.user_id ORDER BY n DESC LIMIT 10"""
                ).fetchall()
            ]
        except Exception:
            from ki import CLOUD_WEEKLY_LIMIT
            ki_today = ki_week = ki_month = ki_users_today = 0
            ki_cloud_week = ki_local_week = ki_luna_week = 0
            ki_top_users = []

        # Ausstehende Wiki-Foto-Einreichungen
        try:
            pending_fotos = conn.execute(
                "SELECT COUNT(*) FROM wiki_foto_submissions WHERE status='pending'"
            ).fetchone()[0]
        except Exception:
            pending_fotos = 0

        # Social Media Tracking
        try:
            social_total     = conn.execute("SELECT COUNT(*) FROM social_content").fetchone()[0]
            social_published = conn.execute(
                "SELECT COUNT(*) FROM social_content WHERE status='published'"
            ).fetchone()[0]
            social_scheduled = conn.execute(
                "SELECT COUNT(*) FROM social_content WHERE status='scheduled'"
            ).fetchone()[0]
            social_ideas     = conn.execute(
                "SELECT COUNT(*) FROM social_content WHERE status='idea'"
            ).fetchone()[0]
            social_this_week = conn.execute(
                "SELECT COUNT(*) FROM social_content WHERE status='published' "
                "AND published_at >= datetime('now', '-7 days')"
            ).fetchone()[0]
            social_by_cat    = {
                row[0]: row[1] for row in conn.execute(
                    "SELECT category, COUNT(*) FROM social_content "
                    "WHERE category IS NOT NULL GROUP BY category ORDER BY 2 DESC"
                ).fetchall()
            }
            social_recent    = [dict(r) for r in conn.execute(
                """SELECT topic, status, platform, format, created_at,
                          published_at, category, ai_score
                   FROM social_content
                   ORDER BY created_at DESC LIMIT 10"""
            ).fetchall()]
        except Exception:
            social_total = social_published = social_scheduled = 0
            social_ideas = social_this_week = 0
            social_by_cat = {}
            social_recent = []

    return {
        "users_total":        users_total,
        "users_today":        users_today,
        "threads":            threads,
        "posts":              posts,
        "open_reports":       open_reports,
        "pending_fotos":      pending_fotos,
        "banned":             banned,
        "dogs_total":         dogs_total,
        "poison_active":      poison_total,
        "push_subscriptions": push_subscriptions,
        "active_users_7d":    active_users_7d,
        "media_count":        media_count,
        "routes_total":       routes_total,
        "events_total":       events_total,
        "osm_total":          osm_total,
        "osm_tiles":          osm_tiles,
        "osm_by_type":        osm_by_type,
        "ki_today":            ki_today,
        "ki_week":             ki_week,
        "ki_month":            ki_month,
        "ki_users_today":      ki_users_today,
        "ki_cloud_week":       ki_cloud_week,
        "ki_local_week":       ki_local_week,
        "ki_luna_week":        ki_luna_week,
        "ki_cloud_weekly_limit": CLOUD_WEEKLY_LIMIT,
        "ki_top_users":        ki_top_users,
        "social_total":       social_total,
        "social_published":   social_published,
        "social_scheduled":   social_scheduled,
        "social_ideas":       social_ideas,
        "social_this_week":   social_this_week,
        "social_by_cat":      social_by_cat,
        "social_recent":      social_recent,
    }


# ------------------------------------------------------------------
# GET /api/admin/users
# ------------------------------------------------------------------
@router.get("/users")
async def list_users(
    q:      str = "",
    rolle:  str = "",
    limit:  int = 50,
    offset: int = 0,
    user=Depends(require_mod),
):
    with db() as conn:
        where = "WHERE 1=1"
        params = []
        if q.strip():
            where += " AND (u.name LIKE ? OR u.email LIKE ?)"
            params.extend([f"%{q.strip()}%", f"%{q.strip()}%"])
        if rolle:
            where += " AND u.rolle = ?"
            params.append(rolle)

        # E-Mail nur für Admins; Moderatoren sehen maskierte Version
        _email_col = "u.email" if user["rolle"] == "admin" else \
                     "SUBSTR(u.email,1,2)||'***@'||SUBSTR(u.email,INSTR(u.email,'@')+1) AS email"
        rows = conn.execute(f"""
            SELECT u.id, u.name, {_email_col}, u.rolle, u.is_premium,
                   u.is_moderator, u.is_banned, u.ban_reason,
                   u.is_founder, u.is_partner, u.founder_number,
                   u.created_at, u.last_login,
                   (SELECT COUNT(*) FROM dogs d WHERE d.user_id=u.id) AS dog_count,
                   (SELECT COUNT(*) FROM forum_threads t WHERE t.user_id=u.id AND t.is_deleted=0) AS thread_count,
                   ROUND(COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=u.id), 0), 1) AS total_km,
                   (SELECT COUNT(*) FROM routes r WHERE r.user_id=u.id) AS route_count,
                   (SELECT COUNT(*) FROM user_map_pois p WHERE p.user_id=u.id) AS poi_count,
                   (SELECT MAX(r.created_at) FROM routes r WHERE r.user_id=u.id) AS last_route
            FROM users u
            {where}
            ORDER BY u.created_at DESC
            LIMIT ? OFFSET ?
        """, [*params, limit, offset]).fetchall()

        total = conn.execute(f"""
            SELECT COUNT(*) FROM users u {where}
        """, params).fetchone()[0]

    return {"users": [dict(r) for r in rows], "total": total}


# ------------------------------------------------------------------
# PATCH /api/admin/users/{id} — Rolle, Sperre
# ------------------------------------------------------------------
@router.patch("/users/{uid}")
async def patch_user(uid: int, data: UserPatch, user=Depends(require_mod)):
    # Rollenwechsel + Privileg-Flags nur für Admins
    if data.rolle is not None and user["rolle"] != "admin":
        raise HTTPException(403, "Rollenwechsel nur für Admins.")
    if data.rolle and data.rolle not in ("user", "moderator", "admin"):
        raise HTTPException(400, "Ungültige Rolle.")
    if data.is_moderator is not None and user["rolle"] != "admin":
        raise HTTPException(403, "is_moderator darf nur von Admins geändert werden.")
    if data.is_social_media is not None and user["rolle"] != "admin":
        raise HTTPException(403, "is_social_media darf nur von Admins geändert werden.")

    with db() as conn:
        target = conn.execute("SELECT id, rolle, name FROM users WHERE id=?", (uid,)).fetchone()
        if not target:
            raise HTTPException(404, "User nicht gefunden.")
        # Mods dürfen keine Admins sperren
        if target["rolle"] == "admin" and user["rolle"] != "admin":
            raise HTTPException(403, "Admins können nur von Admins verwaltet werden.")

        updates = data.model_dump(exclude_none=True)
        if not updates:
            raise HTTPException(400, "Keine Änderungen.")

        # is_moderator aus rolle ableiten wenn rolle gesetzt wird
        if "rolle" in updates:
            updates["is_moderator"] = 1 if updates["rolle"] in ("moderator", "admin") else 0

        cols = ", ".join(f"{k}=?" for k in updates)
        conn.execute(f"UPDATE users SET {cols} WHERE id=?", [*updates.values(), uid])
        row = conn.execute(
            "SELECT id, name, email, rolle, is_moderator, is_banned, ban_reason FROM users WHERE id=?",
            (uid,)
        ).fetchone()

        # Audit
        detail_parts = []
        if "is_banned" in updates:
            detail_parts.append("gesperrt" if updates["is_banned"] else "entsperrt")
        if "rolle" in updates:
            detail_parts.append(f"Rolle→{updates['rolle']}")
        _audit(conn, user, "user_patch", f"user:{uid} ({target['name']})", ", ".join(detail_parts) or None)

    return dict(row)


# ------------------------------------------------------------------
# DELETE /api/admin/users/{id} — Account löschen (Admin only)
# ------------------------------------------------------------------
@router.delete("/users/{uid}", status_code=204)
async def delete_user(uid: int, user=Depends(require_admin)):
    with db() as conn:
        target = conn.execute("SELECT id, rolle, name FROM users WHERE id=?", (uid,)).fetchone()
        if not target:
            raise HTTPException(404, "User nicht gefunden.")
        if target["id"] == user["id"]:
            raise HTTPException(400, "Du kannst deinen eigenen Account nicht löschen.")
        conn.execute("DELETE FROM users WHERE id=?", (uid,))
        _audit(conn, user, "user_delete", f"user:{uid} ({target['name']})")


# ------------------------------------------------------------------
# GET /api/admin/forum/threads — alle Threads inkl. gelöschte
# ------------------------------------------------------------------
@router.get("/forum/threads")
async def admin_threads(
    q:         str = "",
    deleted:   int = 0,
    limit:     int = 50,
    offset:    int = 0,
    user=Depends(require_mod),
):
    with db() as conn:
        where = "WHERE 1=1"
        params = []
        if not deleted:
            where += " AND t.is_deleted=0"
        if q.strip():
            where += " AND (t.titel LIKE ? OR t.text LIKE ?)"
            params.extend([f"%{q.strip()}%", f"%{q.strip()}%"])

        rows = conn.execute(f"""
            SELECT t.id, t.kategorie, t.titel, SUBSTR(t.text,1,100) AS text_preview,
                   t.antworten, t.likes, t.views,
                   t.is_pinned, t.is_locked, t.is_deleted, t.created_at,
                   u.id AS user_id, u.name AS autor_name
            FROM forum_threads t
            LEFT JOIN users u ON u.id=t.user_id
            {where}
            ORDER BY t.created_at DESC
            LIMIT ? OFFSET ?
        """, [*params, limit, offset]).fetchall()

        total = conn.execute(f"""
            SELECT COUNT(*) FROM forum_threads t {where}
        """, params).fetchone()[0]

    return {"threads": [dict(r) for r in rows], "total": total}


# ------------------------------------------------------------------
# PATCH /api/admin/forum/threads/{id}
# ------------------------------------------------------------------
@router.patch("/forum/threads/{tid}")
async def admin_patch_thread(tid: int, data: ThreadAdminPatch, user=Depends(require_mod)):
    with db() as conn:
        thread = conn.execute("SELECT id, titel FROM forum_threads WHERE id=?", (tid,)).fetchone()
        if not thread:
            raise HTTPException(404, "Thread nicht gefunden.")
        updates = data.model_dump(exclude_none=True)
        if not updates:
            raise HTTPException(400, "Keine Änderungen.")
        cols = ", ".join(f"{k}=?" for k in updates)
        conn.execute(f"UPDATE forum_threads SET {cols} WHERE id=?", [*updates.values(), tid])
        _audit(conn, user, "thread_patch", f"thread:{tid}", str(updates))
    return {"ok": True}


# ------------------------------------------------------------------
# DELETE /api/admin/forum/threads/{id}
# ------------------------------------------------------------------
@router.delete("/forum/threads/{tid}", status_code=204)
async def admin_delete_thread(tid: int, user=Depends(require_mod)):
    with db() as conn:
        thread = conn.execute("SELECT id, titel FROM forum_threads WHERE id=?", (tid,)).fetchone()
        if not thread:
            raise HTTPException(404, "Thread nicht gefunden.")
        conn.execute("UPDATE forum_threads SET is_deleted=1 WHERE id=?", (tid,))
        _audit(conn, user, "thread_delete", f"thread:{tid} ({thread['titel'][:60]})")


# ------------------------------------------------------------------
# DELETE /api/admin/forum/posts/{id}
# ------------------------------------------------------------------
@router.delete("/forum/posts/{pid}", status_code=204)
async def admin_delete_post(pid: int, user=Depends(require_mod)):
    with db() as conn:
        post = conn.execute("SELECT * FROM forum_posts WHERE id=?", (pid,)).fetchone()
        if not post:
            raise HTTPException(404, "Beitrag nicht gefunden.")
        conn.execute("UPDATE forum_posts SET is_deleted=1 WHERE id=?", (pid,))
        conn.execute(
            "UPDATE forum_threads SET antworten=MAX(0,antworten-1) WHERE id=?",
            (post["thread_id"],)
        )
        _audit(conn, user, "post_delete", f"post:{pid} thread:{post['thread_id']}")


# ------------------------------------------------------------------
# GET /api/admin/reports — offene Meldungen
# ------------------------------------------------------------------
@router.get("/reports")
async def admin_reports(user=Depends(require_mod)):
    with db() as conn:
        rows = conn.execute("""
            SELECT r.id, r.target_type, r.target_id, r.grund, r.resolved, r.created_at,
                   u.name AS melder_name,
                   CASE r.target_type
                     WHEN 'thread' THEN (SELECT t.titel FROM forum_threads t WHERE t.id=r.target_id)
                     WHEN 'post'   THEN (SELECT SUBSTR(p.text,1,80) FROM forum_posts p WHERE p.id=r.target_id)
                   END AS content_preview
            FROM forum_reports r
            LEFT JOIN users u ON u.id=r.user_id
            ORDER BY r.resolved ASC, r.created_at DESC
            LIMIT 100
        """).fetchall()
    return [dict(r) for r in rows]


# ------------------------------------------------------------------
# PATCH /api/admin/reports/{id} — erledigen / wiedereröffnen
# ------------------------------------------------------------------
@router.patch("/reports/{rid}")
async def admin_resolve_report(rid: int, user=Depends(require_mod)):
    with db() as conn:
        r = conn.execute("SELECT resolved FROM forum_reports WHERE id=?", (rid,)).fetchone()
        if not r:
            raise HTTPException(404, "Meldung nicht gefunden.")
        new_state = 0 if r["resolved"] else 1
        conn.execute(
            "UPDATE forum_reports SET resolved=? WHERE id=?",
            (new_state, rid)
        )
        _audit(conn, user, "report_resolve" if new_state else "report_reopen", f"report:{rid}")
    return {"ok": True}


# ------------------------------------------------------------------
# GET /api/admin/scheduler/jobs
# ------------------------------------------------------------------
@router.get("/scheduler/jobs")
async def scheduler_jobs(user=Depends(require_admin)):
    from scheduler import _scheduler
    jobs = []
    for job in _scheduler.get_jobs():
        next_run = job.next_run_time
        jobs.append({
            "id":            job.id,
            "name":          job.name,
            "next_run_time": next_run.isoformat() if next_run else None,
            "trigger":       str(job.trigger),
        })
    return jobs


# ------------------------------------------------------------------
# POST /api/admin/scheduler/trigger/{job_id}
# ------------------------------------------------------------------
@router.post("/scheduler/trigger/{job_id}")
async def scheduler_trigger(job_id: str, user=Depends(require_admin)):
    from scheduler import _scheduler, _TZ as SCHED_TZ
    job = _scheduler.get_job(job_id)
    if not job:
        raise HTTPException(404, f"Job '{job_id}' nicht gefunden.")
    job.modify(next_run_time=datetime.now(tz=SCHED_TZ))
    with db() as conn:
        _audit(conn, user, "scheduler_trigger", f"job:{job_id}")
    return {"ok": True, "job_id": job_id}


# ------------------------------------------------------------------
# GET /api/admin/ki/history — 30-Tage-Verlauf + Top-User (all-time)
# ------------------------------------------------------------------
@router.get("/ki/history")
async def ki_history(user=Depends(require_mod)):
    with db() as conn:
        daily = conn.execute("""
            SELECT date,
                   SUM(count)                                              AS total,
                   SUM(CASE WHEN source='cloud' THEN count ELSE 0 END)    AS cloud,
                   SUM(CASE WHEN source='local' THEN count ELSE 0 END)    AS local,
                   SUM(CASE WHEN source='luna'  THEN count ELSE 0 END)    AS luna
            FROM ki_daily_calls
            WHERE date >= DATE('now', '-29 days')
            GROUP BY date ORDER BY date ASC
        """).fetchall()
        top_users = conn.execute("""
            SELECT u.name, u.email,
                   SUM(k.count)                                               AS total,
                   SUM(CASE WHEN k.source='cloud' THEN k.count ELSE 0 END)   AS cloud,
                   MAX(k.date)                                                AS last_date
            FROM ki_daily_calls k JOIN users u ON u.id = k.user_id
            GROUP BY k.user_id ORDER BY total DESC LIMIT 15
        """).fetchall()
    return {
        "daily_history": [{"date": r["date"], "total": r["total"],
                           "cloud": r["cloud"], "local": r["local"], "luna": r["luna"]}
                          for r in daily],
        "top_users":     [{"name": r["name"], "email": r["email"],
                           "total": r["total"], "cloud": r["cloud"], "last_date": r["last_date"]}
                          for r in top_users],
    }


# ------------------------------------------------------------------
# GET /api/admin/ki/status — lokale LLM-Erreichbarkeit prüfen
# ------------------------------------------------------------------
@router.get("/ki/status")
async def ki_status(user=Depends(require_mod)):
    import httpx
    from ki import KI_MODE, LOCAL_BASE_URL, LOCAL_MODEL, CLOUD_MODEL, ANTHROPIC_KEY

    result = {
        "mode":                KI_MODE,
        "local_url":           LOCAL_BASE_URL if KI_MODE != "off" else None,
        "local_model_config":  LOCAL_MODEL,
        "local_reachable":     False,
        "local_model_loaded":  None,
        "cloud_model":         CLOUD_MODEL,
        "cloud_key_set":       bool(ANTHROPIC_KEY),
    }

    if KI_MODE != "off":
        try:
            async with httpx.AsyncClient(timeout=3.0) as client:
                resp = await client.get(f"{LOCAL_BASE_URL}/models")
                if resp.status_code == 200:
                    data = resp.json()
                    models = data.get("data", [])
                    result["local_reachable"] = True
                    if models:
                        result["local_model_loaded"] = models[0].get("id")
        except Exception:
            pass

    return result


# ------------------------------------------------------------------
# GET /api/admin/system
# ------------------------------------------------------------------
@router.get("/system")
async def system_info(user=Depends(require_admin)):
    # DB-Größe
    try:
        db_size_mb = os.path.getsize(DB_PATH) / 1024 ** 2
    except OSError:
        db_size_mb = 0.0

    # Media-Größe (rekursiv)
    media_dir = os.getenv("MEDIA_DIR", "/data/media")
    media_size_bytes = 0
    try:
        for dirpath, _dirs, files in os.walk(media_dir):
            for fname in files:
                try:
                    media_size_bytes += os.path.getsize(os.path.join(dirpath, fname))
                except OSError:
                    pass
    except OSError:
        pass
    media_size_mb = media_size_bytes / 1024 ** 2

    # Disk-Info
    disk_total_gb = 0.0
    disk_free_gb  = 0.0
    try:
        st = os.statvfs(DB_PATH)
        disk_total_gb = st.f_blocks * st.f_frsize / 1024 ** 3
        disk_free_gb  = st.f_bavail * st.f_frsize / 1024 ** 3
    except (OSError, AttributeError):
        pass

    # SW-Cache-Version aus sw.js lesen
    sw_version = "?"
    try:
        import re as _re
        static_dir = os.getenv("STATIC_DIR", "/app/static")
        sw_content = open(os.path.join(static_dir, "sw.js")).readline()
        m = _re.search(r"'(by-v\d+)'", sw_content)
        if m:
            sw_version = m.group(1)
    except Exception:
        pass

    return {
        "db_size_mb":     round(db_size_mb, 2),
        "media_size_mb":  round(media_size_mb, 2),
        "uptime_seconds": int(time.time() - _start_time),
        "python_version": sys.version.split()[0],
        "disk_total_gb":  round(disk_total_gb, 2),
        "disk_free_gb":   round(disk_free_gb, 2),
        "sw_version":     sw_version,
    }


# ------------------------------------------------------------------
# GET /api/admin/logs
# ------------------------------------------------------------------
@router.get("/logs")
async def get_logs(lines: int = 200, level: str = "", user=Depends(require_admin)):
    from main import log_buffer
    entries = list(log_buffer)
    if level:
        entries = [e for e in entries if e['l'] == level.upper()]
    return entries[-lines:]


# ------------------------------------------------------------------
# GET /api/admin/audit
# ------------------------------------------------------------------
@router.get("/audit")
async def audit_log(limit: int = 50, user=Depends(require_admin)):
    with db() as conn:
        rows = conn.execute(
            """
            SELECT id, admin_id, admin_name, action, target, detail, created_at
            FROM admin_audit
            ORDER BY id DESC
            LIMIT ?
            """,
            (min(limit, 200),),
        ).fetchall()
    return [dict(r) for r in rows]


# ------------------------------------------------------------------
# GET /api/admin/analytics — Umami-Proxy
# ------------------------------------------------------------------
@router.get("/analytics")
async def get_analytics(user=Depends(require_mod)):
    import httpx
    from datetime import timedelta
    url     = os.getenv("UMAMI_URL", "").rstrip("/")
    site_id = os.getenv("UMAMI_SITE_ID", "")
    if not url or not site_id:
        raise HTTPException(503, "Umami nicht konfiguriert.")
    token   = await _umami_auth()
    headers = {"Authorization": f"Bearer {token}"}

    now         = datetime.now(_TZ)
    today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
    week_start  = today_start - timedelta(days=6)
    month_start = today_start - timedelta(days=29)
    year_start  = today_start - timedelta(days=364)
    now_ms      = int(now.timestamp() * 1000)
    today_ms    = int(today_start.timestamp() * 1000)
    week_ms     = int(week_start.timestamp() * 1000)
    month_ms    = int(month_start.timestamp() * 1000)
    year_ms     = int(year_start.timestamp() * 1000)

    async with httpx.AsyncClient(timeout=15) as c:
        r_today, r_week, r_month, r_pv_month, r_pv_year, r_pages, r_refs = await asyncio.gather(
            c.get(f"{url}/api/websites/{site_id}/stats",
                  params={"startAt": today_ms, "endAt": now_ms}, headers=headers),
            c.get(f"{url}/api/websites/{site_id}/stats",
                  params={"startAt": week_ms,  "endAt": now_ms}, headers=headers),
            c.get(f"{url}/api/websites/{site_id}/stats",
                  params={"startAt": month_ms, "endAt": now_ms}, headers=headers),
            c.get(f"{url}/api/websites/{site_id}/pageviews",
                  params={"startAt": month_ms, "endAt": now_ms,
                          "unit": "day", "timezone": "Europe/Berlin"}, headers=headers),
            c.get(f"{url}/api/websites/{site_id}/pageviews",
                  params={"startAt": year_ms, "endAt": now_ms,
                          "unit": "month", "timezone": "Europe/Berlin"}, headers=headers),
            c.get(f"{url}/api/websites/{site_id}/metrics",
                  params={"startAt": month_ms, "endAt": now_ms,
                          "type": "url", "limit": 10}, headers=headers),
            c.get(f"{url}/api/websites/{site_id}/metrics",
                  params={"startAt": month_ms, "endAt": now_ms,
                          "type": "referrer", "limit": 8}, headers=headers),
        )

    # Monatliche Neuanmeldungen aus lokaler DB (letzte 12 Monate)
    with db() as conn:
        reg_rows = conn.execute("""
            SELECT strftime('%Y-%m', created_at) AS month, COUNT(*) AS count
            FROM users
            WHERE created_at >= date('now', '-12 months')
            GROUP BY month ORDER BY month ASC
        """).fetchall()
    monthly_registrations = [{"month": r["month"], "count": r["count"]} for r in reg_rows]

    def _to_list(r):
        j = r.json()
        if isinstance(j, list):   return j
        if isinstance(j, dict):   return j.get("data", j.get("metrics", []))
        return []

    return {
        "today":                  r_today.json(),
        "week":                   r_week.json(),
        "month":                  r_month.json(),
        "pageviews":              r_pv_month.json(),
        "pageviews_year":         r_pv_year.json(),
        "monthly_registrations":  monthly_registrations,
        "top_pages":              _to_list(r_pages),
        "referrers":              _to_list(r_refs),
    }


# ------------------------------------------------------------------
# POST /api/admin/wiki/enrich — KI-Rassen-Anreicherung anstoßen
# ------------------------------------------------------------------
@router.post("/wiki/enrich")
async def wiki_enrich(data: WikiEnrichBody, user=Depends(require_mod)):
    from scraper.breed_enricher import enrich_breeds
    limit = max(1, min(data.limit, 100))
    enriched = await enrich_breeds(limit)
    with db() as conn:
        remaining = conn.execute(
            "SELECT COUNT(*) FROM wiki_rassen WHERE ki_enriched=0"
        ).fetchone()[0]
    return {"enriched": enriched, "remaining": remaining}


# ------------------------------------------------------------------
# GET /api/admin/wiki/evaluate — LLM-as-Judge Qualitätsbewertung
# ------------------------------------------------------------------
@router.get("/wiki/evaluate")
async def wiki_evaluate(sample: int = 20, user=Depends(require_mod)):
    from scraper.breed_evaluator import evaluate_enrichment
    sample = max(5, min(sample, 50))
    return await evaluate_enrichment(sample_size=sample)


# ------------------------------------------------------------------
# GET /api/admin/wiki/enrichment-status — Enrichment-Statistik
# ------------------------------------------------------------------
@router.get("/wiki/enrichment-status")
async def wiki_enrichment_status(user=Depends(require_mod)):
    with db() as conn:
        total     = conn.execute("SELECT COUNT(*) FROM wiki_rassen").fetchone()[0]
        enriched  = conn.execute("SELECT COUNT(*) FROM wiki_rassen WHERE ki_enriched=1").fetchone()[0]
        no_wiki   = conn.execute("SELECT COUNT(*) FROM wiki_rassen WHERE ki_enriched=2").fetchone()[0]
        pending   = conn.execute("SELECT COUNT(*) FROM wiki_rassen WHERE ki_enriched=0").fetchone()[0]
        by_model  = {
            row[0] or "unbekannt": row[1]
            for row in conn.execute(
                "SELECT ki_model, COUNT(*) FROM wiki_rassen "
                "WHERE ki_enriched=1 GROUP BY ki_model ORDER BY 2 DESC"
            ).fetchall()
        }
        with_photo = conn.execute(
            "SELECT COUNT(*) FROM wiki_rassen WHERE foto_url IS NOT NULL AND foto_url != ''"
        ).fetchone()[0]
    return {
        "total":      total,
        "enriched":   enriched,
        "no_wiki":    no_wiki,
        "pending":    pending,
        "with_photo": with_photo,
        "by_model":   by_model,
    }


# ------------------------------------------------------------------
# POST /api/admin/wiki/fetch-photos — Wiki-Fotos laden
# ------------------------------------------------------------------
@router.post("/wiki/fetch-photos")
async def wiki_fetch_photos(limit: int = 50, user=Depends(require_mod)):
    import asyncio, subprocess
    proc = await asyncio.create_subprocess_exec(
        "python3", "/app/scraper/fetch_wiki_images.py", "--limit", str(limit),
        stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
    )
    stdout, stderr = await proc.communicate()
    lines = (stdout + stderr).decode()
    found = lines.count("Foto gespeichert")
    return {"launched": True, "found": found, "log": lines[-2000:]}


# ------------------------------------------------------------------
# DELETE /api/admin/wiki/zuchter/{id} — Züchter-Eintrag löschen (Admin/Mod)
# ------------------------------------------------------------------
@router.get("/social")
async def admin_social_stats(user=Depends(require_mod)):
    """Social-Media-Übersicht für Admins — alle Manager, alle Plattformen."""
    with db() as conn:
        # Pro Manager: Name + Counts
        managers = conn.execute("""
            SELECT u.id, u.name,
                COUNT(sc.id)                                              AS total,
                COUNT(CASE WHEN sc.status='published' THEN 1 END)        AS published,
                COUNT(CASE WHEN sc.status='idea'      THEN 1 END)        AS ideas,
                COUNT(CASE WHEN sc.status='scheduled' THEN 1 END)        AS scheduled,
                COUNT(CASE WHEN sc.post_url IS NOT NULL
                           AND sc.post_url != ''
                           AND sc.status='published' THEN 1 END)         AS with_link
            FROM users u
            JOIN social_content sc ON sc.created_by = u.id
            GROUP BY u.id
            ORDER BY published DESC
        """).fetchall()

        # Veröffentlichte Posts nach Plattform
        by_platform = conn.execute("""
            SELECT platform, COUNT(*) AS n
            FROM social_content
            WHERE status='published'
            GROUP BY platform
            ORDER BY n DESC
        """).fetchall()

        # Veröffentlichte Posts nach Monat (letzte 6 Monate)
        by_month = conn.execute("""
            SELECT strftime('%Y-%m', published_at) AS monat, COUNT(*) AS n
            FROM social_content
            WHERE status='published' AND published_at IS NOT NULL
            GROUP BY monat
            ORDER BY monat DESC
            LIMIT 6
        """).fetchall()

        # Letzte veröffentlichte Posts mit Link (für Abrechnung/Nachweis)
        recent_published = conn.execute("""
            SELECT sc.id, sc.topic, sc.platform, sc.category,
                   sc.published_at, sc.post_url, sc.ai_score,
                   u.name AS manager
            FROM social_content sc
            LEFT JOIN users u ON u.id = sc.created_by
            WHERE sc.status = 'published'
            ORDER BY sc.published_at DESC
            LIMIT 50
        """).fetchall()

    return {
        "managers":         [dict(r) for r in managers],
        "by_platform":      [dict(r) for r in by_platform],
        "by_month":         [dict(r) for r in by_month],
        "recent_published": [dict(r) for r in recent_published],
    }


@router.delete("/wiki/zuchter/{zuchter_id}", status_code=204)
async def admin_delete_zuchter(zuchter_id: int, user=Depends(require_mod)):
    with db() as conn:
        row = conn.execute(
            "SELECT id FROM wiki_zuchter WHERE id=?", (zuchter_id,)
        ).fetchone()
        if not row:
            raise HTTPException(404, "Züchter nicht gefunden.")
        conn.execute("DELETE FROM wiki_zuchter WHERE id=?", (zuchter_id,))
        _audit(conn, user, "wiki_zuchter_delete", f"zuchter:{zuchter_id}")


# ------------------------------------------------------------------
# POST /api/admin/media/generate-previews — Previews für Bestandsmedien
# ------------------------------------------------------------------
@router.get("/ors/stats")
async def ors_stats(user=Depends(require_mod)):
    """ORS-Routenvorschlag Statistiken für Admin-Panel."""
    with db() as conn:
        # Heute
        today = __import__('datetime').date.today().isoformat()
        today_row = conn.execute(
            "SELECT COALESCE(count,0) as count FROM ors_daily_total WHERE date=?", (today,)
        ).fetchone()
        today_count = today_row["count"] if today_row else 0

        # Letzte 30 Tage (Verlauf)
        daily_history = conn.execute("""
            SELECT date, count FROM ors_daily_total
            WHERE date >= DATE('now', '-29 days')
            ORDER BY date ASC
        """).fetchall()

        # Letzte 8 Wochen (Wochensummen aus route_suggest_usage)
        weekly_totals = conn.execute("""
            SELECT week, SUM(count) as count
            FROM route_suggest_usage
            WHERE week >= DATE('now', '-56 days')
            GROUP BY week ORDER BY week ASC
        """).fetchall()

        # Top-Nutzer (alle Zeiten)
        top_users = conn.execute("""
            SELECT u.name, u.email,
                   SUM(r.count) as total,
                   MAX(r.week)  as last_week
            FROM route_suggest_usage r
            JOIN users u ON u.id = r.user_id
            GROUP BY r.user_id
            ORDER BY total DESC
            LIMIT 15
        """).fetchall()

    return {
        "today_count":   today_count,
        "today_limit":   2000,
        "daily_history": [{"date": r["date"], "count": r["count"]} for r in daily_history],
        "weekly_totals": [{"week": r["week"], "count": r["count"]} for r in weekly_totals],
        "top_users":     [{"name": r["name"], "email": r["email"],
                           "total": r["total"], "last_week": r["last_week"]} for r in top_users],
    }


@router.post("/media/generate-previews")
async def generate_media_previews(user=Depends(require_admin)):
    """Generiert fehlende _preview.jpg für alle Bilder in /data/media."""
    import io as _io
    from media_utils import generate_preview, _PREVIEW_EXTS
    MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media")

    generated = 0
    skipped   = 0
    errors    = 0

    for subdir in ("diary", "forum"):
        folder = os.path.join(MEDIA_DIR, subdir)
        if not os.path.isdir(folder):
            continue
        for fname in os.listdir(folder):
            # Nur Original-Bilder (keine _preview, _thumb, Videos, PDFs)
            low = fname.lower()
            if "_preview" in low or "_thumb" in low:
                continue
            base, ext = os.path.splitext(fname)
            if ext.lower() not in _PREVIEW_EXTS:
                continue
            preview_path = os.path.join(folder, base + "_preview.webp")
            if os.path.exists(preview_path):
                skipped += 1
                continue
            try:
                data = open(os.path.join(folder, fname), "rb").read()
                preview = generate_preview(data, ext)
                if preview:
                    open(preview_path, "wb").write(preview)
                    generated += 1
                else:
                    skipped += 1
            except Exception as exc:
                errors += 1

    return {"generated": generated, "skipped": skipped, "errors": errors}
