from rest_framework import viewsets , generics , status  , filters
from rest_framework.permissions import IsAuthenticated , AllowAny , IsAuthenticatedOrReadOnly
from .models import City, Category, Place, Advertisement , Booking, ContactUs , User , FavoritePlace , EmergencyNumber
from .serializers import  ( CitySerializer, CategorySerializer, PlaceSerializer, AdSerializer ,
 BookingSerializer, ContactUsSerializer ,UserSerializer , FavoritePlaceSerializer , EmergencyNumberSerializer ) 
from django.utils import timezone  
from rest_framework.response import Response
from rest_framework.decorators import action
from django.contrib.auth.password_validation import validate_password
from rest_framework.validators import ValidationError
from django_filters.rest_framework import DjangoFilterBackend
from django.db.models import Q
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.views import APIView
from django.shortcuts import get_object_or_404
from .serializers import FavoritePlaceSerializerCreate
from djoser.views import TokenCreateView
from .serializers import CustomTokenCreateSerializer



class CustomTokenCreateView(TokenCreateView):
    serializer_class = CustomTokenCreateSerializer


    
class UserViewSet(viewsets.ViewSet):
    permission_classes = [IsAuthenticated]

    def get_object(self):
        return self.request.user

    @action(detail=False, methods=['get'])
    def me(self, request):
        user = self.get_object()
        serializer = UserSerializer(user)
        return Response(serializer.data)

    @action(detail=False, methods=['patch'])
    def patch_info(self, request):
        user = self.get_object()
        serializer = UserSerializer(user, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    @action(detail=False, methods=['post'])
    def change_language(self, request):
        user = self.get_object()
        language = request.data.get('preferred_language')
        if language not in dict(User.LANGUAGE_CHOICES):
            return Response({'error': 'Invalid language choice.'}, status=status.HTTP_400_BAD_REQUEST)
        user.preferred_language = language
        user.save()
        return Response({'message': 'Language updated successfully.'})

    @action(detail=False, methods=['post'])
    def change_city(self, request):
        user = self.get_object()
        city_id = request.data.get('city')
        try:
            city = City.objects.get(id=city_id)
        except City.DoesNotExist:
            return Response({'error': 'City not found.'}, status=status.HTTP_404_NOT_FOUND)
        user.city = city
        user.save()
        return Response({'message': 'City updated successfully.'})

    @action(detail=False, methods=['post'])
    def change_password(self, request):
        user = self.get_object()
        old_password = request.data.get('old_password')
        new_password = request.data.get('new_password')

        if not user.check_password(old_password):
            return Response({'error': 'Old password is incorrect.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            validate_password(new_password, user)
        except ValidationError as e:
            return Response({'error': e.messages}, status=status.HTTP_400_BAD_REQUEST)

        user.set_password(new_password)
        user.save()
        return Response({'message': 'Password updated successfully.'})



class AdViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Advertisement.objects.all()
    serializer_class = AdSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        user_city = user.city
        return Advertisement.objects.filter(cities=user_city, is_active=True, expiry_date__gte=timezone.now())


class CityViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = City.objects.all()
    serializer_class = CitySerializer
    permission_classes = [IsAuthenticatedOrReadOnly]


class CategoryViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        user_city = user.city
        return Category.objects.filter(place__city=user_city).distinct()

    @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])
    def filtered(self, request):
        user = self.request.user
        user_city = user.city
        filtered_queryset = Category.objects.filter(
            place__city=user_city, 
            name_en__in=["restaurant", "caffe", "hotel"  , 'hospital']
        ).distinct()
        page = self.paginate_queryset(filtered_queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(filtered_queryset, many=True)
        return Response(serializer.data)

class PlaceViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Place.objects.all()
    serializer_class = PlaceSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['category']
    search_fields = ['name_ar', 'name_en', 'name_ku']

    def get_queryset(self):
        user = self.request.user
        if user.is_authenticated:
            user_city = user.city
        else:
            user_city = 1
        queryset = Place.objects.filter(city=user_city)
        return queryset

    @action(detail=False, methods=['get'], permission_classes=[IsAuthenticatedOrReadOnly])
    def bestplace(self, request):
        user = self.request.user
        if user.is_authenticated:
            user_city = user.city
        else:
            user_city = 1 

        filtered_queryset = Place.objects.filter(city=user_city , rating__gte=4.9).distinct()
        
        page = self.paginate_queryset(filtered_queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(filtered_queryset, many=True)
        return Response(serializer.data)


        # Custom search logic
        # search_query = self.request.query_params.get('search')
        # if search_query:
        #     search_field, search_term = search_query.split('=')
        #     if search_field == 'name':
        #         queryset = queryset.filter(
        #             Q(name_ar__icontains=search_term) |
        #             Q(name_en__icontains=search_term) |
        #             Q(name_ku__icontains=search_term)
        #         )

        # return queryset


class BookingCreateView(generics.CreateAPIView):
    queryset = Booking.objects.all()
    serializer_class = BookingSerializer
    permission_classes = [IsAuthenticated]

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)


class ContactUsCreateView(generics.CreateAPIView):
    queryset = ContactUs.objects.all()
    serializer_class = ContactUsSerializer
    permission_classes = [AllowAny]  




class FavoritePlaceListView(generics.ListAPIView):
    serializer_class = FavoritePlaceSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        # Filter the queryset to only include favorite places for the authenticated user
        return FavoritePlace.objects.filter(user=self.request.user)


class EmergencyNumberViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = EmergencyNumber.objects.all()
    serializer_class = EmergencyNumberSerializer
    permission_classes = [IsAuthenticated]







class CreateFavoritePlaceView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        user = request.user  # Get the user from the request
        serializer = FavoritePlaceSerializerCreate(data=request.data)
        
        if serializer.is_valid():
            place = serializer.validated_data.get('place')
            
            # Check if the place is already in the user's favorite list
            if FavoritePlace.objects.filter(user=user, place=place).exists():
                return Response({'error': 'This place is already in your favorites'}, status=status.HTTP_400_BAD_REQUEST)
            
            # Create the new favorite place
            FavoritePlace.objects.create(user=user, place=place)
            return Response({'success': 'Place added to favorites'}, status=status.HTTP_201_CREATED)
        
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class FavoritePlaceDeleteView(APIView):
    permission_classes = [IsAuthenticated]

    def delete(self, request, *args, **kwargs):
        user = request.user
        place_id = request.query_params.get('id')
        if not place_id:
            return Response({"detail": "Place ID is required in query parameters."}, status=status.HTTP_400_BAD_REQUEST)
        favorite_place = get_object_or_404(FavoritePlace, user=user, place__id=place_id)
        favorite_place.delete()
        return Response(
            {
            "detail": f"Favorite place with ID {place_id} successfully deleted."
            },
            status=status.HTTP_200_OK
        )