from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from django.utils import timezone
from django.contrib.auth.models import User

from master_admin.models import UserSession
from .permissions import is_school_admin


def _get_school_id(request):
    """Extract school_id from the request (middleware sets request.school, JWT has school_id claim)."""
    school = getattr(request, "school", None)
    if school:
        return school.id
    if request.auth:
        return request.auth.get("school_id")
    return None


def _session_to_dict(s):
    return {
        "id": s.id,
        "session_token": str(s.session_token),
        "user_type": s.user_type,
        "external_id": s.external_id,
        "user_id": s.user_id,
        "device_type": s.device_type,
        "device_name": s.device_name,
        "browser": s.browser,
        "ip_address": s.ip_address,
        "logged_in_at": s.logged_in_at,
        "last_active_at": s.last_active_at,
        "is_active": s.is_active,
    }


class ActiveSessionsView(APIView):
    """
    GET  /api/school-admin/sessions/
         Returns all active sessions for this school, grouped by user_type.
         Query param ?type=TEACHER|PARENT filters to one type.
    """

    permission_classes = [IsAuthenticated]

    def get(self, request):
        if not (request.user.is_staff or request.user.is_superuser or is_school_admin(request.user)):
            return Response({"detail": "Permission denied."}, status=status.HTTP_403_FORBIDDEN)

        try:
            school_id = _get_school_id(request)
        except Exception:
            return Response({"detail": "Could not resolve school."}, status=status.HTTP_400_BAD_REQUEST)

        qs = (
            UserSession.objects.using("default")
            .filter(school_id=school_id, is_active=True)
            .order_by("-logged_in_at")
        )

        user_type_filter = request.query_params.get("type", "").upper()
        if user_type_filter in ("TEACHER", "PARENT"):
            qs = qs.filter(user_type=user_type_filter)

        # Enrich with user names from master DB
        user_ids = list(qs.values_list("user_id", flat=True))
        user_map = {
            u.id: f"{u.first_name} {u.last_name}".strip() or u.email
            for u in User.objects.using("default").filter(id__in=user_ids)
        }

        sessions = [_session_to_dict(s) for s in qs]
        for s in sessions:
            s["name"] = user_map.get(s["user_id"], "")

        teachers = [s for s in sessions if s["user_type"] == "TEACHER"]
        parents = [s for s in sessions if s["user_type"] == "PARENT"]

        return Response(
            {
                "teachers": teachers,
                "parents": parents,
                "total": len(sessions),
            }
        )


class ForceLogoutSessionView(APIView):
    """
    POST /api/school-admin/sessions/<session_id>/force-logout/
         Blacklists the refresh token and marks the session as inactive.
    """

    permission_classes = [IsAuthenticated]

    def post(self, request, session_id):
        if not (request.user.is_staff or request.user.is_superuser or is_school_admin(request.user)):
            return Response({"detail": "Permission denied."}, status=status.HTTP_403_FORBIDDEN)

        try:
            school_id = _get_school_id(request)
        except Exception:
            return Response({"detail": "Could not resolve school."}, status=status.HTTP_400_BAD_REQUEST)

        try:
            session = UserSession.objects.using("default").get(
                id=session_id, school_id=school_id
            )
        except UserSession.DoesNotExist:
            return Response({"detail": "Session not found."}, status=status.HTTP_404_NOT_FOUND)

        if not session.is_active:
            return Response({"detail": "Session is already inactive."}, status=status.HTTP_400_BAD_REQUEST)

        # Blacklist the refresh token so it can't be used to get new access tokens
        if session.refresh_jti:
            try:
                from rest_framework_simplejwt.token_blacklist.models import (
                    OutstandingToken,
                    BlacklistedToken,
                )

                outstanding = OutstandingToken.objects.filter(jti=session.refresh_jti).first()
                if outstanding:
                    BlacklistedToken.objects.get_or_create(token=outstanding)
            except Exception:
                pass

        session.is_active = False
        session.logged_out_at = timezone.now()
        session.save(using="default", update_fields=["is_active", "logged_out_at"])

        return Response({"success": True, "message": "Session terminated successfully."})


class BulkForceLogoutView(APIView):
    """
    POST /api/school-admin/sessions/bulk-logout/
         Body: { "session_ids": [1, 2, 3] } or { "user_type": "TEACHER" } to logout all of a type.
    """

    permission_classes = [IsAuthenticated]

    def post(self, request):
        if not (request.user.is_staff or request.user.is_superuser or is_school_admin(request.user)):
            return Response({"detail": "Permission denied."}, status=status.HTTP_403_FORBIDDEN)

        try:
            school_id = _get_school_id(request)
        except Exception:
            return Response({"detail": "Could not resolve school."}, status=status.HTTP_400_BAD_REQUEST)

        session_ids = request.data.get("session_ids", [])
        user_type = request.data.get("user_type", "").upper()

        qs = UserSession.objects.using("default").filter(school_id=school_id, is_active=True)

        if session_ids:
            qs = qs.filter(id__in=session_ids)
        elif user_type in ("TEACHER", "PARENT"):
            qs = qs.filter(user_type=user_type)
        else:
            return Response(
                {"detail": "Provide session_ids or user_type."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        sessions = list(qs)

        # Blacklist all refresh tokens
        jti_list = [s.refresh_jti for s in sessions if s.refresh_jti]
        if jti_list:
            try:
                from rest_framework_simplejwt.token_blacklist.models import (
                    OutstandingToken,
                    BlacklistedToken,
                )

                for outstanding in OutstandingToken.objects.filter(jti__in=jti_list):
                    BlacklistedToken.objects.get_or_create(token=outstanding)
            except Exception:
                pass

        now = timezone.now()
        qs.update(is_active=False, logged_out_at=now)

        return Response({"success": True, "terminated": len(sessions)})
