"""Ban Yaro — Gamification: Badges, Streaks, Punkte"""

from datetime import date, timedelta
from fastapi import APIRouter, Depends
from database import db
from auth import get_current_user

router = APIRouter()

# ------------------------------------------------------------------
# Tier-Definitionen
# ------------------------------------------------------------------
TIERS = {
    "bronze":  {"name": "Bronze",  "color": "#cd7f32", "dark": "#7c4a0a", "text": "#fff"},
    "silber":  {"name": "Silber",  "color": "#94a3b8", "dark": "#475569", "text": "#fff"},
    "gold":    {"name": "Gold",    "color": "#f59e0b", "dark": "#b45309", "text": "#fff"},
    "platin":  {"name": "Platin",  "color": "#cbd5e1", "dark": "#94a3b8", "text": "#1e293b"},
    "diamant": {"name": "Diamant", "color": "#67e8f9", "dark": "#0891b2", "text": "#fff"},
}

TIER_ORDER = ["bronze", "silber", "gold", "platin", "diamant"]

# ------------------------------------------------------------------
# Badge-Kategorien mit Stufen
# ------------------------------------------------------------------
CATEGORIES = [
    {
        "id":     "km",
        "name":   "Kilometer",
        "emoji":  "🐾",
        "metrik": "total_km",
        "einheit": "km",
        "stufen": [
            ("bronze",  5,    "Erste Schritte"),
            ("silber",  25,   "Vielläufer"),
            ("gold",    100,  "100-km-Club"),
            ("platin",  500,  "Ausdauer-Profi"),
            ("diamant", 2000, "Unermüdlich"),
        ],
    },
    {
        "id":     "routen",
        "name":   "Routen",
        "emoji":  "🗺️",
        "metrik": "routen",
        "einheit": "",
        "stufen": [
            ("bronze",  1,   "Entdecker"),
            ("silber",  5,   "Kartograph"),
            ("gold",    20,  "Routen-Profi"),
            ("platin",  50,  "Gassi-Legende"),
            ("diamant", 100, "Route-König"),
        ],
    },
    {
        "id":     "pois",
        "name":   "POIs",
        "emoji":  "📍",
        "metrik": "pois",
        "einheit": "",
        "stufen": [
            ("bronze",  1,   "Pfadfinder"),
            ("silber",  5,   "Community-Held"),
            ("gold",    20,  "Botschafter"),
            ("platin",  50,  "Karten-Profi"),
            ("diamant", 100, "Legende"),
        ],
    },
    {
        "id":     "streak",
        "name":   "Streak",
        "emoji":  "🔥",
        "metrik": "streak",
        "einheit": " Tage",
        "stufen": [
            ("bronze",  3,   "Auf Trab"),
            ("silber",  7,   "Wochenheld"),
            ("gold",    30,  "Monatsläufer"),
            ("platin",  100, "Eiserne Pfote"),
            ("diamant", 365, "Ein ganzes Jahr"),
        ],
    },
    {
        "id":     "wiki_fotos",
        "name":   "Wiki-Fotos",
        "emoji":  "📸",
        "metrik": "wiki_fotos",
        "einheit": " Foto(s)",
        "stufen": [
            ("bronze",  1,  "Erster Klick"),
            ("silber",  3,  "Foto-Fan"),
            ("gold",    10, "Wiki-Fotograf"),
        ],
    },
]

# Flat-Liste aller Badge-IDs für DB-Kompatibilität
def _all_badge_ids():
    ids = []
    for cat in CATEGORIES:
        for tier, _, _ in cat["stufen"]:
            ids.append(f"{cat['id']}_{tier}")
    return ids


# ------------------------------------------------------------------
# Streak aktualisieren
# ------------------------------------------------------------------
def update_streak(user_id: int, conn):
    today = date.today().isoformat()
    row = conn.execute(
        "SELECT current_streak, max_streak, last_activity_date FROM users WHERE id=?",
        (user_id,)
    ).fetchone()
    if not row:
        return

    last = row["last_activity_date"]
    cur  = row["current_streak"] or 0
    mx   = row["max_streak"] or 0

    if last == today:
        return

    yesterday = (date.today() - timedelta(days=1)).isoformat()
    cur = cur + 1 if last == yesterday else 1
    mx  = max(mx, cur)
    conn.execute(
        "UPDATE users SET current_streak=?, max_streak=?, last_activity_date=? WHERE id=?",
        (cur, mx, today, user_id)
    )


# ------------------------------------------------------------------
# Badges prüfen und vergeben
# ------------------------------------------------------------------
def check_and_award(user_id: int, conn):
    stats = conn.execute("""
        SELECT ROUND(
                   COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=? AND r.is_valid=1), 0) +
                   COALESCE((SELECT SUM(w.walked_km)  FROM route_walks w WHERE w.user_id=?), 0),
               1) AS total_km,
               (SELECT COUNT(*) FROM routes r WHERE r.user_id=? AND r.is_valid=1) AS routen,
               (SELECT COUNT(*) FROM user_map_pois p WHERE p.user_id=?)            AS pois,
               (SELECT COUNT(*) FROM wiki_foto_submissions WHERE user_id=? AND status='approved') AS wiki_fotos
        FROM (SELECT 1)
    """, (user_id, user_id, user_id, user_id, user_id)).fetchone()

    streak_row = conn.execute(
        "SELECT current_streak FROM users WHERE id=?", (user_id,)
    ).fetchone()

    metrics = {
        "total_km":  stats["total_km"]   if stats else 0,
        "routen":    stats["routen"]     if stats else 0,
        "pois":      stats["pois"]       if stats else 0,
        "streak":    (streak_row["current_streak"] if streak_row else 0),
        "wiki_fotos": stats["wiki_fotos"] if stats else 0,
    }

    earned = {r["badge_id"] for r in
              conn.execute("SELECT badge_id FROM user_badges WHERE user_id=?",
                           (user_id,)).fetchall()}

    new_badges = []
    for cat in CATEGORIES:
        val = metrics.get(cat["metrik"], 0)
        for tier, schwelle, badge_name in cat["stufen"]:
            bid = f"{cat['id']}_{tier}"
            if bid not in earned and val >= schwelle:
                conn.execute(
                    "INSERT OR IGNORE INTO user_badges (user_id, badge_id) VALUES (?,?)",
                    (user_id, bid)
                )
                new_badges.append({
                    "id": bid, "name": badge_name,
                    "emoji": cat["emoji"],
                    "tier": TIERS[tier]["name"],
                })
    return new_badges


# ------------------------------------------------------------------
# API
# ------------------------------------------------------------------
@router.get("/me")
async def my_achievements(user=Depends(get_current_user)):
    uid = user["id"]
    with db() as conn:
        update_streak(uid, conn)
        new_badges = check_and_award(uid, conn)

        stats = conn.execute("""
            SELECT ROUND(
                       COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=? AND r.is_valid=1), 0) +
                       COALESCE((SELECT SUM(w.walked_km)  FROM route_walks w WHERE w.user_id=?), 0),
                   1) AS total_km,
                   (SELECT COUNT(*) FROM routes r WHERE r.user_id=? AND r.is_valid=1) AS routen,
                   (SELECT COUNT(*) FROM user_map_pois p WHERE p.user_id=?)            AS pois,
                   (SELECT COUNT(*) FROM wiki_foto_submissions WHERE user_id=? AND status='approved') AS wiki_fotos,
                   ROUND(
                       COALESCE((SELECT SUM(r.distanz_km) FROM routes r WHERE r.user_id=? AND r.is_valid=1), 0) +
                       COALESCE((SELECT SUM(w.walked_km)  FROM route_walks w WHERE w.user_id=?), 0),
                   1)*1
                   + (SELECT COUNT(*) FROM user_map_pois p WHERE p.user_id=?)*5
                   + (SELECT COUNT(*) FROM routes r WHERE r.user_id=? AND r.is_valid=1)*10 AS punkte
            FROM (SELECT 1)
        """, (uid, uid, uid, uid, uid, uid, uid, uid, uid)).fetchone()

        streak_row = conn.execute(
            "SELECT current_streak, max_streak FROM users WHERE id=?", (uid,)
        ).fetchone()

        earned_rows = conn.execute(
            "SELECT badge_id FROM user_badges WHERE user_id=?", (uid,)
        ).fetchall()
        earned_ids = {r["badge_id"] for r in earned_rows}

        rank_row = conn.execute("""
            SELECT COUNT(*)+1 AS rang FROM (
                SELECT u.id,
                    ROUND(COALESCE(SUM(r.distanz_km),0),1)*1
                    +COUNT(DISTINCT p.id)*5
                    +COUNT(DISTINCT r.id)*10 AS punkte
                FROM users u
                LEFT JOIN routes r ON r.user_id=u.id AND r.is_valid=1
                LEFT JOIN user_map_pois p ON p.user_id=u.id
                GROUP BY u.id
            ) WHERE punkte > ?
        """, (stats["punkte"] if stats else 0,)).fetchone()

    metrics = {
        "total_km":  stats["total_km"]   if stats else 0,
        "routen":    stats["routen"]     if stats else 0,
        "pois":      stats["pois"]       if stats else 0,
        "streak":    (streak_row["current_streak"] if streak_row else 0),
        "wiki_fotos": stats["wiki_fotos"] if stats else 0,
    }

    # Kategorien mit aktuellem Tier + Fortschritt aufbauen
    badge_categories = []
    for cat in CATEGORIES:
        val = metrics.get(cat["metrik"], 0)
        current_tier = None
        next_tier    = None
        next_thresh  = None
        prev_thresh  = 0

        for tier, schwelle, badge_name in cat["stufen"]:
            bid = f"{cat['id']}_{tier}"
            if val >= schwelle:
                current_tier = {"tier": tier, "badge_id": bid,
                                "name": badge_name, **TIERS[tier]}
                prev_thresh = schwelle
            else:
                if next_tier is None:
                    next_tier   = {"tier": tier, "badge_id": bid,
                                   "name": badge_name, "schwelle": schwelle,
                                   **TIERS[tier]}
                    next_thresh = schwelle
                break

        # Fortschritt zur nächsten Stufe in %
        if next_thresh:
            progress = round(min((val - prev_thresh) / (next_thresh - prev_thresh) * 100, 99))
        else:
            progress = 100

        badge_categories.append({
            "id":           cat["id"],
            "name":         cat["name"],
            "emoji":        cat["emoji"],
            "einheit":      cat["einheit"],
            "current_value": val,
            "current_tier": current_tier,
            "next_tier":    next_tier,
            "progress":     progress,
            "alle_stufen": [
                {
                    "tier": tier, "schwelle": schwelle, "name": badge_name,
                    "earned": f"{cat['id']}_{tier}" in earned_ids,
                    **TIERS[tier],
                }
                for tier, schwelle, badge_name in cat["stufen"]
            ],
        })

    return {
        "stats":      dict(stats) if stats else {},
        "streak":     {"current": streak_row["current_streak"] if streak_row else 0,
                       "max":     streak_row["max_streak"]     if streak_row else 0},
        "rang":       rank_row["rang"] if rank_row else 1,
        "categories": badge_categories,
        "new_badges": new_badges,
    }
