from rest_framework import generics, mixins, viewsets, serializers, status, filters
from rest_framework.response import Response
from rest_framework.views import APIView
#from rest_framework import viewsets
from .models import * 
from .serializers import *
from django.shortcuts import get_object_or_404
from rest_framework.renderers import TemplateHTMLRenderer, StaticHTMLRenderer
from rest_framework.decorators import api_view, renderer_classes, permission_classes, throttle_classes, action
from django_filters import rest_framework as django_filters
#from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination

from rest_framework.permissions import IsAuthenticated, SAFE_METHODS, IsAdminUser, BasePermission
#from rest_framework.throttling import AnonRateThrottle, UserRateThrottle
#from .throttles import TenCallsPerMinute
from django.contrib.auth.models import User, Group
import pandas as pd
import numpy as np
from .apps import *
from django.core.cache import caches, cache as default_cache



# Create your views here.


class SetPagination(PageNumberPagination):
    page_size = 20
    page_size_query_param = 'page_size'
    max_page_size = 10000

class OfficeFilter(django_filters.FilterSet):

    class Meta:
        model = Offices
        fields = {
            'office_id': ['exact'],
            'name': ['icontains'],
            'website': ['icontains'],
            'logo': ['icontains'],
            'telephone': ['icontains'],
            'country': ['icontains'],
            'country_abbreviation': ['icontains'],
            'state': ['icontains'],
            'state_abbreviation': ['icontains'],
            'city': ['icontains'],
            'zone': ['icontains'],
            'neighborhood': ['icontains'],
            'complement': ['icontains'],
            'address': ['icontains'],
            'street_number': ['icontains'],
            'postal_code': ['icontains'],
            'total_properties': ['in', 'exact'],
        }



class OfficeView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Offices.objects.using('mongodb').all()
    serializer_class = OfficeSerializer
    name = "Offices"
    description = "Offices Endpoint"
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = OfficeFilter
    search_fields=['name', 'website', 'logo', 'telephone', 'country', 'country_abbreviation', 'state',
                   'state_abbreviation', 'city', 'zone', 'neighborhood', 'complement', 'address', 'street_number'
                   'postal_code']
    ordering_fields = '__all__'
    ordering = ['office_id']
    pagination_class = SetPagination
    
    def get(self, request, *args, **kwargs):
        # Check if a specific key exists in the cache
        if cache.get('example_key'):
            print("Cache hit!")
        else:
            # Set the key in the cache if it doesn't exist
            cache.set('example_key', 'example_value', timeout=60)
            print("Cache miss!")

        return super().get(request, *args, **kwargs)
    
class SingleOfficeView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Offices.objects.using('mongodb').all()
    serializer_class = OfficeSerializer
    name = "Office"
    description = "Office Endpoint"
    

class AgentFilter(django_filters.FilterSet):

    class Meta:
        model = Agents
        fields = {
            'agent_id': ['exact'],
            'name': ['icontains'],
            'email': ['contains'],
            'total_properties': ['in', 'exact'],
            'profile_picture': ['contains'],

            'office__office_id': ['exact'],
            'office__name': ['icontains'],
            'office__website': ['icontains'],
            'office__logo': ['icontains'],
            'office__telephone': ['icontains'],
            'office__country': ['icontains'],
            'office__country_abbreviation': ['icontains'],
            'office__state': ['icontains'],
            'office__state_abbreviation': ['icontains'],
            'office__city': ['icontains'],
            'office__zone': ['icontains'],
            'office__neighborhood': ['icontains'],
            'office__complement': ['icontains'],
            'office__address': ['icontains'],
            'office__street_number': ['icontains'],
            'office__postal_code': ['icontains'],
            'office__total_properties': ['in', 'exact'],
        }


class AgentView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Agents.objects.using('mongodb').all()
    serializer_class = AgentSerializer
    name = "Agents"
    description = "Agents Endpoint"
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = AgentFilter
    search_fields=['name', 'email','office__name', 'office__website', 'office__logo', 'office__telephone',
                   'office__country', 'office__country_abbreviation', 'office__state',
                   'office__state_abbreviation', 'office__city', 'office__zone', 'office__neighborhood',
                   'office__complement', 'office__address', 'office__street_number'
                   'office__postal_code']
    ordering_fields = '__all__'
    ordering = ['agent_id']
    pagination_class = SetPagination

class SingleAgentView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Agents.objects.using('mongodb').all()
    serializer_class = AgentSerializer
    name = "Agent"
    description = "Agent Endpoint"
    

class FeatureFilter(django_filters.FilterSet):

    class Meta:
        model = Features
        fields = {
            'feature_id': ['exact'],
            'feature_name_en': ['icontains'],
            'feature_name_pt': ['icontains'],
        }

class FeatureView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Features.objects.using('mongodb').all()
    serializer_class = FeatureSerializer
    name = "Features"
    description = "Features Endpoint"
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = FeatureFilter
    search_fields=['feature_name_en', 'feature_name_pt',]
    ordering_fields = '__all__'
    ordering = ['feature_id']
    pagination_class = SetPagination

class SingleFeatureView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Features.objects.using('mongodb').all()
    serializer_class = FeatureSerializer
    name = "Feature"
    description = "Feature Endpoint"


class UsageFilter(django_filters.FilterSet):

    class Meta:
        model = Usages
        fields = {
            'usage_id': ['exact'],
            'usage_name_en': ['icontains'],
            'usage_name_pt': ['icontains'],
        }

class UsageView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Usages.objects.using('mongodb').all()
    serializer_class = UsageSerializer
    name = "Usages"
    description = "Usages Endpoint"
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = UsageFilter
    search_fields=['usage_name_en', 'usage_name_pt',]
    ordering_fields = '__all__'
    ordering = ['usage_id']
    pagination_class = SetPagination

class SingleUsageView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Usages.objects.using('mongodb').all()
    serializer_class = UsageSerializer
    name = "Usage"
    description = "Usage Endpoint"
    
    

class TypeFilter(django_filters.FilterSet):

    class Meta:
        model = Types
        fields = {
            'type_id': ['exact'],
            'type_name_en': ['icontains'],
            'type_name_pt': ['icontains'],
            'usage__usage_name_en': ['icontains'],
            'usage__usage_name_pt': ['icontains'],
        }

class TypeView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Types.objects.using('mongodb').all()
    serializer_class = TypeSerializer
    name = "Types"
    description = "Types Endpoint"
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = TypeFilter
    search_fields=['type_name_en', 'type_name_pt', 'usage__usage_name_en', 'usage__usage_name_pt',]
    ordering_fields = '__all__'
    ordering = ['type_id']
    pagination_class = SetPagination

class SingleTypeView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Types.objects.using('mongodb').all()
    serializer_class = TypeSerializer
    name = "Type"
    description = "Type Endpoint"
    


class LocationFilter(django_filters.FilterSet):

    class Meta:
        model = Location
        fields = {
            'property_location_id': ['exact'],
            'display_address': ['icontains'],
            'country': ['icontains'],
            'country_abbreviation': ['icontains'],
            'state': ['icontains'],
            'city': ['icontains'],
            'zone': ['icontains'],
            'neighborhood': ['icontains'],
            'complement': ['icontains'],
            'address': ['icontains'],
            'street_number': ['icontains'],
            'postal_code': ['icontains'],              
        }

class LocationView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Location.objects.using('mongodb').all()
    serializer_class = LocationSerializer
    name = "Locations"
    description = "Properties Location Endpoint"
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = LocationFilter
    search_field = ['country', 'country_abbreviation', 'state', 'city', 'zone', 'neighborhood', 'complement',
                    'address', 'street_number', 'postal_code']
    ordering_fields = '__all__'
    ordering = ['property_location_id',]
    pagination_class = SetPagination
    
class SingleLocationView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Location.objects.using('mongodb').all()
    serializer_class = LocationSerializer
    name = "Location"
    description = "Property Location Endpoint"
    


class PropertyFilter(django_filters.FilterSet):
    list_price= django_filters.RangeFilter(
        field_name='list_price',

    )
    living_area= django_filters.RangeFilter(
        field_name='living_area',
   
    )
    publish_date= django_filters.DateFilter(
        field_name='publish_date',

   
    )
    sync_date= django_filters.DateFilter(
            field_name='sync_date',

 
    )
    
    
    class Meta:
        model = Properties
        fields = {
            'listing_id': ['in', 'exact'],
            'title': ['icontains'],
            'transaction_type': ['icontains'],
            'detail_view_url': ['icontains'],
            'description': ['icontains'],
            'list_price': ['range','exact'],
            'list_price_currency': ['exact'],
            'rental_price' : ['range','exact'],
            'rental_price_currency': ['exact'],
            'rental_price_period': ['icontains'],
            'property_administration_fee' : ['range','exact'],
            'property_administration_fee_period': ['icontains'],
            'yearly_tax': ['range', 'exact'],
            'yearly_tax_currency': ['exact'],
            'living_area': ['range', 'exact'],
            'living_area_unit': ['exact'],
            'year_built' : ['in', 'exact'],
            'bedrooms': ['in', 'exact', 'range'],
            'bathrooms': ['in','exact', 'range'],
            'garage': ['in', 'exact', 'range'],
            'garage_type': ['exact'],
            'unit_floor': ['in', 'exact', 'range'],
            'unit_number': ['in', 'exact'],
            'publish_date': ['exact', 'range', 'icontains'],
            'sync_date': ['exact', 'range'],
            'region_id': ['in', 'exact'],
            'office__office_id': ['in', 'exact'],
            'office__name': ['in', 'exact','icontains'],
            'office__website': ['icontains'],
            'office__logo': ['icontains'],
            'office__telephone': ['icontains'],
            'office__country': ['icontains'],
            'office__country_abbreviation': ['exact'],
            'office__state': ['icontains'],
            'office__state_abbreviation': ['exact'],
            'office__city': ['icontains'],
            'office__zone': ['icontains'],
            'office__neighborhood': ['icontains'],
            'office__complement': ['icontains'],
            'office__address': ['icontains'],
            'office__street_number': ['exact'],
            'office__postal_code': ['exact'],
            'office__total_properties': ['in', 'exact', 'range'],
            'agent__agent_id': ['exact'],
            'agent__name': ['exact', 'icontains'],
            'agent__agent_id': ['exact'],
            'agent__name': ['exact', 'icontains'],
            'agent__email': ['icontains'],
            'agent__total_properties':['in', 'exact', 'range'],
            'agent__agent_id': ['exact'],
            'agent__name': ['exact', 'icontains'],
            'usage__usage_id': ['exact'],
            'usage__usage_name_en': ['exact', 'icontains'],
            'usage__usage_name_pt': ['exact', 'icontains'],
            'type__type_id': ['exact'],
            'type__type_name_en': ['exact', 'icontains'],
            'type__type_name_pt': ['exact', 'icontains'],
            'location__property_location_id': ['in', 'exact'],
            'location__display_address': ['icontains'],
            'location__country': ['in', 'exact','icontains'],
            'location__country_abbreviation': ['in','icontains'],
            'location__state': ['in', 'icontains'],
            'location__zone': ['in', 'icontains'],
            'location__neighborhood': ['in', 'icontains'],
            'location__complement': ['icontains'],
            'location__address': ['in', 'icontains'],
            'location__street_number': ['icontains'],
            'location__postal_code': ['icontains'],
            'medias__url': ['icontains'],
            'features__feature__feature_name_en': ['in', 'icontains'],
            'features__feature__feature_name_pt': ['in', 'icontains'],
        }


class PropertyView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Properties.objects.using('mongodb').all()
    serializer_class = PropertySerializer
    name = "Properties"
    description = "Properties Endpoint"
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = PropertyFilter
    search_fields = ['listing_id', 'title', 'property_type', 'description', 'list_price', 'rental_price', 'living_area', 'bedrooms', 'bathrooms',
                     'year_built', 'garage', 'garage_type', 'unit_floor', 'unit_number', 'office__name', 'office__website',
                     'office__telephone','agent__name', 'agent__email', 'usage__usage_name_en', 'usage__usage_name_pt',
                     'type__type_name_en', 'type__type_name_pt', 'location__display_address',
                    'location__country', 'location__country_abbreviation', 'location__state',
                    'location__zone', 'location__neighborhood', 'location__complement', 'location__address',
                    'location__postal_code']
    ordering_fields = '__all__'
    ordering = ['property_id']
    pagination_class = SetPagination

class SinglePropertyView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Properties.objects.using('mongodb').all()
    serializer_class = PropertySerializer
    name = "Property"
    description = "Property Endpoint"


class PropertyMediaFilter(django_filters.FilterSet):
    """
    main = django_filters.filters.ModelMultipleChoiceFilter(
        field_name='main',
        to_field_name='main',
        queryset=PropertiesMedia.objects.only('main').order_by('main').distinct()
    )
    """
    class Meta:
        model = PropertiesMedia
        fields = {
            'property_media_id': ['in', 'exact'],
            'type': ['contains'],
            'main':['exact'],
            'url': ['contains'],
            'property__property_id': ['exact'],
            'property__listing_id': ['exact'],
            'property__title': ['icontains'],
            'property__transaction_type': ['icontains'],
            'property__detail_view_url': ['icontains'],
            'property__usage__usage_name_en': ['icontains'],
            'property__usage__usage_name_pt': ['icontains'],
            'property__type__type_name_en': ['icontains'],
            'property__type__type_name_pt': ['icontains'],
            'property__description': ['icontains'],
            'property__list_price': ['range','exact'],
            'property__rental_price': ['range','exact'],
            'property__list_price_currency': ['exact'],
            'property__rental_price_currency': ['exact'],
            'property__living_area': ['range', 'exact'],
            'property__living_area_unit': ['exact'],
            'property__year_built': ['exact'],
            'property__bedrooms': ['exact', 'range', 'icontains'],
            'property__bathrooms': ['exact', 'range', 'icontains'],
            'property__garage': ['exact', 'range', 'icontains'],
            'property__garage_type': ['exact'],
            'property__unit_floor': ['exact', 'range', 'icontains'],
            'property__unit_number': ['exact'],
            'property__publish_date': ['exact', 'range', 'icontains'],
            'property__sync_date': ['exact', 'range'],
            'property__region_id': ['exact'],
        }


class PropertyMediaView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = PropertiesMedia.objects.using('mongodb').all()
    serializer_class = PropertyMediaSerializer
    name = "Medias"
    description = "Properties Media Endpoint"
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = PropertyMediaFilter
    search_fields= []
    ordering_fields = '__all__'
    ordering = ['property_media_id',]
    pagination_class = SetPagination
    
class SinglePropertyMediaView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = PropertiesMedia.objects.using('mongodb').all()
    serializer_class = PropertyMediaSerializer
    name = "Media"
    description = "Property Media Endpoint"
    

class PropertyFeatureFilter(django_filters.FilterSet):
    """
    item = django_filters.filters.ModelMultipleChoiceFilter(
        field_name='item',
        to_field_name='item',
        queryset=PropertiesFeatures.objects.all(),
    )    
    """
    class Meta:
        model = PropertiesFeatures
        fields = {
            'property_feature_id': ['in', 'exact'],
            'feature__feature_name_en': ['in', 'exact', 'contains'],
            'feature__feature_name_pt': ['in', 'exact', 'contains'],
            'property__property_id': ['exact'],
            'property__listing_id': ['exact'],
            'property__listing_id': ['exact'],
            'property__title': ['icontains'],
            'property__transaction_type': ['icontains'],
            'property__detail_view_url': ['icontains'],
            'property__usage__usage_name_en': ['icontains'],
            'property__usage__usage_name_pt': ['icontains'],
            'property__type__type_name_en': ['icontains'],
            'property__type__type_name_pt': ['icontains'],
            'property__description': ['icontains'],
            'property__list_price': ['range','exact'],
            'property__rental_price': ['range','exact'],
            'property__list_price_currency': ['exact'],
            'property__rental_price_currency': ['exact'],
            'property__living_area': ['range', 'exact'],
            'property__living_area_unit': ['exact'],
            'property__year_built': ['exact'],
            'property__bedrooms': ['exact', 'range', 'icontains'],
            'property__bathrooms': ['exact', 'range', 'icontains'],
            'property__garage': ['exact', 'range', 'icontains'],
            'property__garage_type': ['exact'],
            'property__unit_floor': ['exact', 'range', 'icontains'],
            'property__unit_number': ['exact'],
            'property__publish_date': ['exact', 'range', 'icontains'],
            'property__sync_date': ['exact', 'range'],
            'property__region_id': ['exact'],
 

        }


class PropertyFeatureView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    #queryset = PropertiesFeatures.objects.all()
    queryset = PropertiesFeatures.objects.using('mongodb').all()
    #queryset = PropertiesFeatures.objects.select_related('feature', 'property')
    serializer_class = PropertyFeatureSerializer
    name = "Features"
    description = "Properties Feature Endpoint"
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = PropertyFeatureFilter
    search_fields = '__all__'
    ordering_fields = '__all__'
    ordering = ['property_feature_id',]
    pagination_class = SetPagination

class SinglePropertyFeatureView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = PropertiesFeatures.objects.using('mongodb').all()
    serializer_class = PropertyFeatureSerializer
    name = "Feature"
    description = "Property Feature Endpoint"



from django.core.cache import cache

def my_view(request):
    data = cache.get("my_key")
    if data is None:
        # Data not found in cache, perform some computation or database query
        # and then store the result in the cache
        data = compute_data_or_query_database()
        cache.set("my_key", data, timeout=300)  # Cache data for 300 seconds (5 minutes)

    # Use the data from the cache
    return HttpResponse(data)