from rest_framework_simplejwt.exceptions import TokenError, InvalidToken
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.views import APIView
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from rest_framework_simplejwt.token_blacklist.models import (
    BlacklistedToken,
    OutstandingToken,
)
import logging

logger = logging.getLogger(__name__)


class MobileRefreshTokenView(APIView):
    """
    Mobile app refresh token endpoint.
    Accepts refresh token in request body (not cookies).
    Returns new access token.
    """

    permission_classes = [AllowAny]
    authentication_classes = []

    def post(self, request):
        refresh_token = request.data.get("refresh_token")

        if not refresh_token:
            return Response(
                {
                    "success": False,
                    "message": "Refresh token is required",
                    "error_code": "REFRESH_TOKEN_REQUIRED",
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        try:
            # First check if token is blacklisted
            try:
                # Get the token from OutstandingToken
                token = RefreshToken(refresh_token)

                # Check if this token's jti is blacklisted
                if BlacklistedToken.objects.filter(token__jti=token["jti"]).exists():
                    logger.warning(
                        f"Attempt to use blacklisted refresh token: {token['jti']}"
                    )
                    return Response(
                        {
                            "success": False,
                            "message": "Refresh token has been revoked",
                            "error_code": "TOKEN_BLACKLISTED",
                        },
                        status=status.HTTP_401_UNAUTHORIZED,
                    )

            except Exception as e:
                # If we can't even parse the token, it's invalid
                logger.warning(f"Invalid token format: {e}")
                return Response(
                    {
                        "success": False,
                        "message": "Invalid refresh token",
                        "error_code": "INVALID_REFRESH_TOKEN",
                    },
                    status=status.HTTP_401_UNAUTHORIZED,
                )

            # Validate and process refresh token
            refresh = RefreshToken(refresh_token)

            # Double-check blacklist after validation
            if BlacklistedToken.objects.filter(token__jti=refresh["jti"]).exists():
                return Response(
                    {
                        "success": False,
                        "message": "Refresh token has been revoked",
                        "error_code": "TOKEN_BLACKLISTED",
                    },
                    status=status.HTTP_401_UNAUTHORIZED,
                )

            # Get new access token
            new_access_token = str(refresh.access_token)

            response_data = {
                "success": True,
                "access_token": new_access_token,
                "token_type": "Bearer",
                "expires_in": 86400,  # 24 hours in seconds
            }

            # Token rotation - always rotate for better security
            try:
                # Blacklist the old refresh token
                refresh.blacklist()

                # Generate new refresh token
                new_refresh_token = str(refresh)
                response_data["refresh_token"] = new_refresh_token

                logger.info(f"Token rotated successfully. Old token blacklisted.")

            except AttributeError:
                # Blacklist app not installed
                logger.warning("Blacklist app not installed. Token rotation disabled.")
                pass
            except Exception as e:
                logger.error(f"Failed to blacklist token during refresh: {e}")

            return Response(response_data, status=status.HTTP_200_OK)

        except TokenError as e:
            logger.warning(f"Token error during refresh: {e}")
            return Response(
                {
                    "success": False,
                    "message": "Invalid or expired refresh token",
                    "error_code": "INVALID_REFRESH_TOKEN",
                },
                status=status.HTTP_401_UNAUTHORIZED,
            )
        except Exception as e:
            logger.error(f"Refresh token error: {str(e)}")
            return Response(
                {
                    "success": False,
                    "message": "Failed to refresh token",
                    "error_code": "REFRESH_FAILED",
                },
                status=status.HTTP_500_INTERNAL_SERVER_ERROR,
            )
