from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from rest_framework_simplejwt.tokens import RefreshToken

from apps.users.firebase import verify_firebase_token
from apps.users.models import User
from apps.users.serializers import (
    FirebaseTokenSerializer,
    LogoutSerializer,
    UserSerializer,
    UserUpdateSerializer,
)


class AuthViewSet(viewsets.ViewSet):
    """ViewSet for authentication (Firebase exchange, logout, profile)."""

    def get_permissions(self):
        if self.action == "firebase":
            return [AllowAny()]
        return [IsAuthenticated()]

    @action(detail=False, methods=["post"], url_path="firebase")
    def firebase(self, request):
        """POST /auth/firebase/ — exchange Firebase ID token for JWT."""
        serializer = FirebaseTokenSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        id_token = serializer.validated_data["id_token"]
        decoded = verify_firebase_token(id_token)

        if decoded is None:
            return Response(
                {"detail": "Invalid or expired Firebase token."},
                status=status.HTTP_401_UNAUTHORIZED,
            )

        firebase_uid = decoded.get("uid")
        phone = decoded.get("phone_number")

        if not firebase_uid:
            return Response(
                {"detail": "Firebase token missing UID."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Validate UAE phone number
        if phone and not phone.startswith("+971"):
            return Response(
                {"detail": "Only UAE phone numbers (+971) are allowed."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        # Get or create user
        user, created = User.objects.get_or_create(
            firebase_uid=firebase_uid,
            defaults={
                "username": firebase_uid,
                "phone_number": phone,
            },
        )

        # Update phone if changed
        if phone and user.phone_number != phone:
            user.phone_number = phone
            user.save(update_fields=["phone_number"])

        # Issue Django JWT
        refresh = RefreshToken.for_user(user)

        return Response(
            {
                "access": str(refresh.access_token),
                "refresh": str(refresh),
                "user": UserSerializer(user).data,
                "is_new_user": created,
            },
            status=status.HTTP_200_OK,
        )

    @action(detail=False, methods=["post"], url_path="logout")
    def logout(self, request):
        """POST /auth/logout/ — blacklist refresh token."""
        serializer = LogoutSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        try:
            token = RefreshToken(serializer.validated_data["refresh"])
            token.blacklist()
        except Exception:
            return Response(
                {"detail": "Invalid token."},
                status=status.HTTP_400_BAD_REQUEST,
            )
        return Response({"detail": "Logged out successfully."}, status=status.HTTP_200_OK)

    @action(detail=False, methods=["get", "patch"], url_path="me")
    def me(self, request):
        """GET/PATCH /auth/me/ — retrieve or update profile."""
        user = request.user

        if request.method == "GET":
            return Response(UserSerializer(user).data)

        # PATCH
        serializer = UserUpdateSerializer(user, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(UserSerializer(user).data)
