"""
Views für den AI Agent.

Endpunkte:
  POST /agent/chat/        – Neue Nachricht senden (startet neue oder bestehende Session)
  GET  /agent/chat/stream/ – SSE-Stream für laufende Anfrage
  GET  /agent/sessions/    – Liste der Chat-Sitzungen (JSON)
  DELETE /agent/sessions/<id>/ – Sitzung löschen
"""
from __future__ import annotations

import json
import logging

from django.contrib.auth.decorators import login_required
from django.core.cache import cache
from django.http import (
    HttpResponse,
    JsonResponse,
    StreamingHttpResponse,
)
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods

from .models import AgentConfig, ChatSession, ChatMessage
from .orchestrator import run_agent_stream

logger = logging.getLogger(__name__)

RATE_LIMIT_PER_MINUTE = 20


def _check_rate_limit(user_id: int) -> bool:
    """Einfaches Rate-Limiting via Django-Cache (Redis). True = erlaubt."""
    key = f"agent_rl_{user_id}"
    count = cache.get(key, 0)
    if count >= RATE_LIMIT_PER_MINUTE:
        return False
    cache.set(key, count + 1, timeout=60)
    return True


def _require_agent_permission(user) -> bool:
    """Prüft ob der Benutzer den Agent nutzen darf."""
    return (
        user.is_superuser
        or user.has_perm("stiftung.can_use_agent")
    )


@login_required
@require_http_methods(["GET"])
def agent_index(request):
    """Einstiegsseite für den Chat (wird als Modal geöffnet, nicht direkt navigiert)."""
    config = AgentConfig.get_config()
    return JsonResponse({
        "provider": config.provider,
        "model": config.model_name,
        "allow_write": config.allow_write,
    })


@login_required
@require_http_methods(["POST"])
def agent_chat(request):
    """
    Startet oder setzt einen Chat fort.

    Body (JSON):
      {
        "message": "Wie viele aktive Destinatäre gibt es?",
        "session_id": "optional-uuid",
        "page_context": "optional – aktueller Seiteninhalt als Text"
      }

    Antwort:
      {
        "session_id": "...",
        "stream_url": "/agent/chat/stream/?session_id=..."
      }
    """
    if not _require_agent_permission(request.user):
        return JsonResponse({"error": "Keine Berechtigung für den AI-Assistenten."}, status=403)

    if not _check_rate_limit(request.user.id):
        return JsonResponse(
            {"error": "Rate-Limit erreicht. Bitte warten Sie eine Minute."},
            status=429,
        )

    try:
        body = json.loads(request.body)
    except (json.JSONDecodeError, ValueError):
        return JsonResponse({"error": "Ungültiger JSON-Body."}, status=400)

    message = (body.get("message") or "").strip()
    if not message:
        return JsonResponse({"error": "Nachricht darf nicht leer sein."}, status=400)

    page_context = (body.get("page_context") or "")[:2000]
    session_id = body.get("session_id")

    # Session ermitteln oder neu erstellen
    session = None
    if session_id:
        try:
            session = ChatSession.objects.get(id=session_id, user=request.user)
        except ChatSession.DoesNotExist:
            pass

    if session is None:
        session = ChatSession.objects.create(user=request.user)

    # Nachricht + Page-Context in Cache für Stream-Endpunkt speichern
    cache_key = f"agent_pending_{session.id}"
    cache.set(
        cache_key,
        {"message": message, "page_context": page_context},
        timeout=300,  # 5 Minuten
    )

    return JsonResponse({
        "session_id": str(session.id),
        "stream_url": f"/agent/chat/stream/?session_id={session.id}",
    })


@login_required
@require_http_methods(["GET"])
def agent_chat_stream(request):
    """
    SSE-Endpunkt: streamt die Antwort des Agenten.

    Query-Params:
      session_id: UUID der Chat-Sitzung
    """
    if not _require_agent_permission(request.user):
        return HttpResponse("Keine Berechtigung.", status=403)

    session_id = request.GET.get("session_id")
    if not session_id:
        return HttpResponse("session_id fehlt.", status=400)

    session = get_object_or_404(ChatSession, id=session_id, user=request.user)

    cache_key = f"agent_pending_{session.id}"
    pending = cache.get(cache_key)
    if not pending:
        return HttpResponse("Keine ausstehende Nachricht gefunden.", status=400)

    cache.delete(cache_key)
    message = pending["message"]
    page_context = pending.get("page_context", "")

    def event_stream():
        try:
            yield from run_agent_stream(
                session=session,
                user_message=message,
                page_context=page_context,
                user=request.user,
            )
        except Exception as e:
            logger.error("Agent-Stream-Fehler: %s", e, exc_info=True)
            import json
            yield f"data: {json.dumps({'type': 'error', 'message': 'Interner Fehler.'})}\n\n"

    response = StreamingHttpResponse(
        event_stream(),
        content_type="text/event-stream",
    )
    response["Cache-Control"] = "no-cache"
    response["X-Accel-Buffering"] = "no"
    return response


@login_required
@require_http_methods(["GET"])
def agent_sessions(request):
    """Gibt die Chat-Sitzungen des Benutzers zurück (letzte 20)."""
    if not _require_agent_permission(request.user):
        return JsonResponse({"error": "Keine Berechtigung."}, status=403)

    sessions = ChatSession.objects.filter(user=request.user).order_by("-updated_at")[:20]
    data = []
    for s in sessions:
        data.append({
            "id": str(s.id),
            "title": s.title or "Neue Unterhaltung",
            "created_at": s.created_at.isoformat(),
            "updated_at": s.updated_at.isoformat(),
            "message_count": s.messages.count(),
        })
    return JsonResponse({"sessions": data})


@login_required
@require_http_methods(["GET"])
def agent_session_messages(request, session_id):
    """Gibt alle Nachrichten einer Sitzung zurück."""
    if not _require_agent_permission(request.user):
        return JsonResponse({"error": "Keine Berechtigung."}, status=403)

    session = get_object_or_404(ChatSession, id=session_id, user=request.user)
    messages = session.messages.exclude(role="tool").order_by("created_at")
    data = []
    for m in messages:
        data.append({
            "id": str(m.id),
            "role": m.role,
            "content": m.content,
            "created_at": m.created_at.isoformat(),
        })
    return JsonResponse({
        "session_id": str(session.id),
        "title": session.title,
        "messages": data,
    })


@login_required
@require_http_methods(["POST"])
def agent_session_delete(request, session_id):
    """Löscht eine Chat-Sitzung."""
    if not _require_agent_permission(request.user):
        return JsonResponse({"error": "Keine Berechtigung."}, status=403)

    session = get_object_or_404(ChatSession, id=session_id, user=request.user)
    session.delete()
    return JsonResponse({"ok": True})
