#from django.shortcuts import render
#from django.http import HttpResponse
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.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.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.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','profile_picture','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_fields = ['has_profile_picture']
    pagination_class = SetPagination


class SingleAgentView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Agents.objects.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.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.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.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.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.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.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'],
            'lat': ['exact'],  
            'lng': ['exact'],            
        }

class LocationView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Location.objects.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','lat', 'lng',]
    ordering_fields = '__all__'
    ordering = ['property_location_id',]
    pagination_class = SetPagination
    
class SingleLocationView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Location.objects.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',

 
    )
    
    #Procurar por MultipleChoiceFilter
    #https://django-filter.readthedocs.io/en/stable/ref/filters.html#modelmultiplechoicefilter
    """
    bedrooms = django_filters.filters.ModelMultipleChoiceFilter(
        field_name='bedrooms',
        to_field_name='bedrooms',
        queryset = Properties.objects.only('bedrooms').order_by('bedrooms').distinct(),
    )

    bathrooms = django_filters.filters.ModelMultipleChoiceFilter(
        field_name='bathrooms',
        to_field_name='bathrooms',
        queryset=Properties.objects.only('bathrooms').order_by('bathrooms').distinct()
    )
    unit_floor = django_filters.filters.ModelMultipleChoiceFilter(
        field_name='unit_floor',
        to_field_name='unit_floor',
        queryset=Properties.objects.only('unit_floor').order_by('unit_floor').distinct()
    )
    garage = django_filters.filters.ModelMultipleChoiceFilter(
        field_name='garage',
        to_field_name='garage',
        queryset=Properties.objects.only('garage').order_by('garage').distinct()
    )
    property_type = django_filters.filters.ModelMultipleChoiceFilter(
            field_name='property_type',
            to_field_name='property_type',
            queryset=Properties.objects.only('property_type').order_by('property_type').distinct()
        )
    
    features__item = django_filters.filters.ModelMultipleChoiceFilter(
            field_name='item',
            to_field_name='item',
            queryset=PropertiesFeatures.objects.only('item').order_by('item').distinct()
        )
    """
    #location__country = django_filters.ModelChoiceFilter(queryset=PropertiesLocation.objects.only('country').order_by('country').distinct())
    #office__name = django_filters.ModelChoiceFilter(queryset=Offices.objects.only('name').order_by('name').distinct())
    #agent__name = django_filters.ModelChoiceFilter(queryset=Agents.objects.only('name').order_by('name').distinct())
    
    
    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', 'gte'],
            'bathrooms': ['in','exact', 'range', 'gte'],
            'garage': ['in', 'exact', 'range', 'gte'],
            'garage_type': ['exact'],
            'unit_floor': ['in', 'exact', 'range', 'gte'],
            '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'],
            'location__lat': ['exact'],
            'location__lng': ['exact'],
            'medias__url': ['icontains'],
            'features__feature__feature_name_en': ['in', 'icontains'],
            'features__feature__feature_name_pt': ['in', 'icontains'],
        }

from django.db.models import Min, Max
class PropertyView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Properties.objects.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

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        # Get the minimum and maximum list_price and rental_price values
        min_list_price = self.queryset.aggregate(Min('list_price'))['list_price__min']
        max_list_price = self.queryset.aggregate(Max('list_price'))['list_price__max']
        min_rental_price = self.queryset.aggregate(Min('rental_price'))['rental_price__min']
        max_rental_price = self.queryset.aggregate(Max('rental_price'))['rental_price__max']
        min_living_area = self.queryset.aggregate(Min('living_area'))['living_area__min']
        max_living_area = self.queryset.aggregate(Max('living_area'))['living_area__max']

        # Paginate the queryset
        paginator = SetPagination()
        page = paginator.paginate_queryset(queryset, request)

        # Serialize the queryset
        serializer = self.get_serializer(page, many=True)

        # Create the response data dictionary
        data = {
            'count': self.queryset.count(),
            'num_pages': paginator.page.paginator.num_pages,
            'current_count': len(serializer.data),
            'next': paginator.get_next_link(),
            'previous': paginator.get_previous_link(),
            'min_list_price': min_list_price,
            'max_list_price': max_list_price,
            'min_rental_price': min_rental_price,
            'max_rental_price': max_rental_price,
            'min_living_area': min_living_area,
            'max_living_area': max_living_area,
            'results': serializer.data
        }

        #return paginator.get_paginated_response(data)
        return Response(data)

class SinglePropertyView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Properties.objects.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.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.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.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.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)