"""Browser sessions keep refresh credentials in an HttpOnly cookie.

The existing JSON token API remains available for non-browser clients.
Cookie-authenticated mutations always enforce CSRF, including login and logout.
"""
from django.conf import settings
from django.middleware.csrf import get_token
from rest_framework import permissions, status
from rest_framework.authentication import SessionAuthentication
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.exceptions import TokenError
from rest_framework_simplejwt.tokens import RefreshToken

from .serializers import LoginSerializer, RefreshSerializer
from .throttles import AccountIPThrottle, AccountEmailThrottle

COOKIE_NAME = "ftg_refresh"
COOKIE_PATH = "/api/v1/users/browser/"


def set_refresh_cookie(response, refresh):
    response.set_cookie(
        COOKIE_NAME, refresh, httponly=True, secure=not settings.DEBUG,
        samesite="Strict", path=COOKIE_PATH,
        max_age=int(settings.SIMPLE_JWT["REFRESH_TOKEN_LIFETIME"].total_seconds()),
    )


class BrowserAccountView(APIView):
    authentication_classes = []
    permission_classes = [permissions.AllowAny]
    throttle_classes = [AccountIPThrottle]
    throttle_scope = "account_refresh"

    def enforce_csrf(self, request):
        SessionAuthentication().enforce_csrf(request)


class BrowserCSRFView(BrowserAccountView):
    def get(self, request):
        response = Response({"csrfToken": get_token(request)})
        response["Cache-Control"] = "no-store"
        return response


class BrowserLoginView(BrowserAccountView):
    throttle_classes = [AccountIPThrottle, AccountEmailThrottle]
    throttle_scope = "account_login"

    def post(self, request):
        self.enforce_csrf(request)
        serializer = LoginSerializer(data=request.data)
        serializer.context['request']=request
        serializer.is_valid(raise_exception=True)
        response = Response({"access": serializer.validated_data["access"]})
        set_refresh_cookie(response, serializer.validated_data["refresh"])
        response["Cache-Control"] = "no-store"
        return response


class BrowserRefreshView(BrowserAccountView):
    def post(self, request):
        self.enforce_csrf(request)
        refresh = request.COOKIES.get(COOKIE_NAME)
        if not refresh:
            raise AuthenticationFailed("Session expired.")
        serializer = RefreshSerializer(data={"refresh": refresh})
        try:
            serializer.is_valid(raise_exception=True)
        except (TokenError, AuthenticationFailed):
            response = Response({"detail": "Session expired."}, status=status.HTTP_401_UNAUTHORIZED)
            response.delete_cookie(COOKIE_NAME, path=COOKIE_PATH, samesite="Strict")
            response["Cache-Control"] = "no-store"
            return response
        response = Response({"access": serializer.validated_data["access"]})
        set_refresh_cookie(response, serializer.validated_data["refresh"])
        response["Cache-Control"] = "no-store"
        return response


class BrowserLogoutView(BrowserAccountView):
    def post(self, request):
        self.enforce_csrf(request)
        refresh = request.COOKIES.get(COOKIE_NAME)
        if refresh:
            try:
                token=RefreshToken(refresh)
                token.blacklist()
                from .security_models import AccountSession
                from django.utils import timezone
                if token.get('session_id'):
                    AccountSession.objects.filter(pk=token['session_id'],user_id=token['user_id'],revoked_at__isnull=True).update(revoked_at=timezone.now())
            except TokenError:
                pass  # Expired/revoked cookies must still be cleared.
        response = Response(status=status.HTTP_204_NO_CONTENT)
        response.delete_cookie(COOKIE_NAME, path=COOKIE_PATH, samesite="Strict")
        response["Cache-Control"] = "no-store"
        return response
