"""BAN YARO — Events (Hundeveranstaltungen)"""

import math
from datetime import date
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from typing import Optional
from database import db
from auth import get_current_user

router = APIRouter()

TYPEN = {'ausstellung', 'training', 'treffen', 'markt', 'wettkampf', 'sonstiges'}


def _haversine(lat1, lon1, lat2, lon2):
    R  = 6_371_000
    p1, p2 = math.radians(lat1), math.radians(lat2)
    dp = math.radians(lat2 - lat1)
    dl = math.radians(lon2 - lon1)
    a  = math.sin(dp / 2) ** 2 + math.cos(p1) * math.cos(p2) * math.sin(dl / 2) ** 2
    return 2 * R * math.asin(math.sqrt(a))


# ------------------------------------------------------------------
# Schemas
# ------------------------------------------------------------------
class RsvpCreate(BaseModel):
    status: str = 'going'  # 'going' | 'maybe'

class EventCreate(BaseModel):
    titel:       str
    datum:       str                       # YYYY-MM-DD
    uhrzeit:     Optional[str]  = None
    lat:         Optional[float] = None
    lon:         Optional[float] = None
    ort_name:    Optional[str]  = None
    typ:         str            = 'sonstiges'
    beschreibung: Optional[str] = None
    link:        Optional[str]  = None

class EventUpdate(BaseModel):
    titel:        Optional[str]   = None
    datum:        Optional[str]   = None
    uhrzeit:      Optional[str]   = None
    lat:          Optional[float] = None
    lon:          Optional[float] = None
    ort_name:     Optional[str]   = None
    typ:          Optional[str]   = None
    beschreibung: Optional[str]   = None
    link:         Optional[str]   = None


# ------------------------------------------------------------------
# GET /api/events
# ------------------------------------------------------------------
@router.get("")
async def list_events(
    lat:    Optional[float] = None,
    lon:    Optional[float] = None,
    radius: int             = 50000,
    typ:    Optional[str]   = None,
    alle:   bool            = False,
    quelle: Optional[str]   = None,
):
    today = date.today().isoformat()
    with db() as conn:
        q = """
            SELECT e.*,
              CASE WHEN e.user_id = 0 THEN 'VDH' ELSE u.name END AS veranstalter_name,
              e.quelle,
              (SELECT COUNT(*) FROM event_rsvp r WHERE r.event_id = e.id AND r.status = 'going') AS rsvp_count
            FROM events e
            LEFT JOIN users u ON u.id = e.user_id AND e.user_id != 0
            WHERE e.status = 'aktiv'
        """
        if not alle:
            q += f" AND e.datum >= '{today}'"
        if typ and typ in TYPEN:
            q += f" AND e.typ = '{typ}'"
        if quelle:
            q += f" AND e.quelle = '{quelle}'"
        q += " ORDER BY e.datum ASC, e.uhrzeit ASC"
        rows = conn.execute(q).fetchall()

    result = [dict(r) for r in rows]
    if lat is not None and lon is not None:
        result = [r for r in result
                  if r['lat'] is None or _haversine(lat, lon, r['lat'], r['lon']) <= radius]
    return result


# ------------------------------------------------------------------
# POST /api/events
# ------------------------------------------------------------------
@router.post("", status_code=201)
async def create_event(data: EventCreate, user=Depends(get_current_user)):
    if data.typ not in TYPEN:
        raise HTTPException(400, f"Ungültiger Typ. Erlaubt: {', '.join(TYPEN)}")
    with db() as conn:
        cur = conn.execute("""
            INSERT INTO events (user_id, titel, datum, uhrzeit, lat, lon, ort_name, typ, beschreibung, link, quelle)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'nutzer')
        """, (user['id'], data.titel, data.datum, data.uhrzeit,
              data.lat, data.lon, data.ort_name,
              data.typ, data.beschreibung, data.link))
        row = conn.execute(
            "SELECT e.*, CASE WHEN e.user_id = 0 THEN 'VDH' ELSE u.name END AS veranstalter_name, e.quelle, "
            "0 AS rsvp_count "
            "FROM events e LEFT JOIN users u ON u.id = e.user_id AND e.user_id != 0 WHERE e.id = ?",
            (cur.lastrowid,)
        ).fetchone()
    return dict(row)


# ------------------------------------------------------------------
# GET /api/events/{id}
# ------------------------------------------------------------------
@router.get("/{event_id}")
async def get_event(event_id: int):
    with db() as conn:
        row = conn.execute(
            "SELECT e.*, CASE WHEN e.user_id = 0 THEN 'VDH' ELSE u.name END AS veranstalter_name, e.quelle, "
            "(SELECT COUNT(*) FROM event_rsvp r WHERE r.event_id = e.id AND r.status = 'going') AS rsvp_count "
            "FROM events e LEFT JOIN users u ON u.id = e.user_id AND e.user_id != 0 WHERE e.id = ?",
            (event_id,)
        ).fetchone()
    if not row:
        raise HTTPException(404, "Event nicht gefunden.")
    return dict(row)


# ------------------------------------------------------------------
# PATCH /api/events/{id}
# ------------------------------------------------------------------
@router.patch("/{event_id}")
async def update_event(event_id: int, data: EventUpdate, user=Depends(get_current_user)):
    with db() as conn:
        ev = conn.execute("SELECT * FROM events WHERE id = ?", (event_id,)).fetchone()
        if not ev:
            raise HTTPException(404, "Event nicht gefunden.")
        if ev['user_id'] == 0 or ev['user_id'] != user['id']:
            raise HTTPException(403, "Nur der Veranstalter kann das Event bearbeiten.")
        updates = data.model_dump(exclude_none=True)
        if updates:
            if 'typ' in updates and updates['typ'] not in TYPEN:
                raise HTTPException(400, "Ungültiger Typ.")
            cols = ', '.join(f"{k} = ?" for k in updates)
            conn.execute(f"UPDATE events SET {cols} WHERE id = ?", [*updates.values(), event_id])
        row = conn.execute(
            "SELECT e.*, CASE WHEN e.user_id = 0 THEN 'VDH' ELSE u.name END AS veranstalter_name, e.quelle, "
            "(SELECT COUNT(*) FROM event_rsvp r WHERE r.event_id = e.id AND r.status = 'going') AS rsvp_count "
            "FROM events e LEFT JOIN users u ON u.id = e.user_id AND e.user_id != 0 WHERE e.id = ?",
            (event_id,)
        ).fetchone()
    return dict(row)


# ------------------------------------------------------------------
# DELETE /api/events/{id}
# ------------------------------------------------------------------
@router.delete("/{event_id}", status_code=204)
async def delete_event(event_id: int, user=Depends(get_current_user)):
    with db() as conn:
        ev = conn.execute("SELECT * FROM events WHERE id = ?", (event_id,)).fetchone()
        if not ev:
            raise HTTPException(404, "Event nicht gefunden.")
        if ev['user_id'] == 0 or ev['user_id'] != user['id']:
            raise HTTPException(403, "Nur der Veranstalter kann das Event löschen.")
        conn.execute("UPDATE events SET status = 'geloescht' WHERE id = ?", (event_id,))


# ------------------------------------------------------------------
# POST /api/events/{id}/rsvp
# ------------------------------------------------------------------
@router.post("/{event_id}/rsvp", status_code=201)
async def rsvp_event(event_id: int, data: RsvpCreate, user=Depends(get_current_user)):
    if data.status not in ('going', 'maybe'):
        raise HTTPException(400, "Status muss 'going' oder 'maybe' sein.")
    with db() as conn:
        ev = conn.execute("SELECT id FROM events WHERE id = ? AND status = 'aktiv'", (event_id,)).fetchone()
        if not ev:
            raise HTTPException(404, "Event nicht gefunden.")
        conn.execute(
            "INSERT OR REPLACE INTO event_rsvp (event_id, user_id, status) VALUES (?, ?, ?)",
            (event_id, user['id'], data.status)
        )
        count = conn.execute(
            "SELECT COUNT(*) FROM event_rsvp WHERE event_id = ? AND status = 'going'", (event_id,)
        ).fetchone()[0]
    return {"event_id": event_id, "status": data.status, "rsvp_count": count}


# ------------------------------------------------------------------
# DELETE /api/events/{id}/rsvp
# ------------------------------------------------------------------
@router.delete("/{event_id}/rsvp", status_code=204)
async def cancel_rsvp(event_id: int, user=Depends(get_current_user)):
    with db() as conn:
        conn.execute(
            "DELETE FROM event_rsvp WHERE event_id = ? AND user_id = ?",
            (event_id, user['id'])
        )


# ------------------------------------------------------------------
# GET /api/events/{id}/rsvp
# ------------------------------------------------------------------
@router.get("/{event_id}/rsvp")
async def list_rsvp(event_id: int):
    with db() as conn:
        rows = conn.execute(
            "SELECT r.user_id, u.name, r.status "
            "FROM event_rsvp r "
            "JOIN users u ON u.id = r.user_id "
            "WHERE r.event_id = ? "
            "ORDER BY r.created_at ASC",
            (event_id,)
        ).fetchall()
    return [dict(r) for r in rows]
