#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 *

class SetPagination(PageNumberPagination):
    page_size = 5000
    page_size_query_param = 'page_size'
    max_page_size = 2


class AssinantesFilter(django_filters.FilterSet):

    class Meta:
        model = Assinantes
        fields = {
            'nome': ['contains'],
            'sobrenome': ['contains'],
            'email': ['contains'],
            'razao_social': ['contains'],
            'nome_fantasia': ['contains'],
            'regiao__bairro': ['contains'],
            'regiao__cidade': ['contains'],
            'regiao__estado': ['contains'],
            'estado_civil__estado_civil': ['contains'],
        }


class AssinantesView(generics.ListCreateAPIView, mixins.CreateModelMixin, mixins.UpdateModelMixin, 
                     mixins.DestroyModelMixin, BasePermission):
#class AssinantesView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = AssinanteSerializer
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = AssinantesFilter
    search_fields=['nome','sobrenome','email', 'razao_social','nome_fantasia','regiao__bairro','regiao__cidade','regiao__estado','estado__estado_civil']
    ordering_fields = ['assinante_id', 'nome','razao_social','nome_fantasia']
    ordering = ['assinante_id']
    pagination_class = SetPagination
    name = "Assinantes"
    description = "Assinantes EndPoint"
    
    def __str__(self) -> str:
        return f"Assinante {self.nome} {self.sobrenome}"
    
    def __repr__(self):
        return self.__str__()
    
   
    def get_queryset(self):
        try:
            query = self.request.data
            if query is not None:
                return Assinantes.objects.all()
            else:
                return Response({"detail":query})
        except:
            return Response({"detail":"Error!"})
    
    def list(self, request):
        try:
            items = self.get_queryset()
            items = self.filter_queryset(items)
            items = self.paginate_queryset(items)
            if items:
                serialized_items = AssinanteSerializer(items, many=True)
                return Response(serialized_items.data)
            else:
                return Response({"detail":"Not Found!"})
        except:
            return Response({"detail":"Error List"})
    
    def get_object(self, request):
        item = self.get_queryset()
        filter = {}
        for field in self.multiple_lookup_fields:
            filter[field] = self.kwargs[field]

        obj = get_object_or_404(item, **filter)
        self.check_object_permissions(self.request, obj)
        return obj
    
    def perform_create(self, serializer):
        permission_classes = [IsAuthenticated]
        serializer.save(user=self.request.user)
    
    def perform_update(self, serializer):
        permission_classes = [IsAuthenticated]
        instance = serializer.save()
    
    def perform_destroy(self, instance):
        permission_classes = [IsAuthenticated]
        instance = instance.destroy()

class AssinaturasFilter(django_filters.FilterSet):

    class Meta:
        model = Assinaturas
        fields = {
            'assinatura_data': ('lte', 'gte'),
            'status': ['contains'],
            'plano__plano': ['contains'],
            'assinante__nome': ['contains'],
            'assinante__sobrenome': ['contains'],
            'assinante__email': ['contains'],
            'assinante__razao_social': ['contains'],
            'assinante__nome_fantasia': ['contains'],
            'assinante__regiao__bairro': ['contains'],
            'assinante__regiao__cidade': ['contains'],
            'assinante__regiao__estado': ['contains'],
            'assinante__estado_civil__estado_civil': ['contains'],
        }

#class AssinaturasView(generics.ListCreateAPIView, mixins.CreateModelMixin, mixins.UpdateModelMixin, 
#                     mixins.DestroyModelMixin, BasePermission):
class AssinaturasView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = AssinanteSerializer
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = AssinaturasFilter
    search_fields=['status','plano__plano','assinante__nome', 'assinante__sobrenome','assinante__nome_fantasia',
                   'assinante__razao_social','assinante__regiao__bairro','assinante__regiao__cidade','assinante__regiao__estado',
                   'assinante__estado_civil__estado_civil']
    ordering_fields = ['assinatura_id', 'assinatura_data','plano']
    ordering = ['assinatura_id']
    pagination_class = SetPagination
    name = "Assinaturas"
    description = "Assinaturas EndPoint"
    
    
    
    def __str__(self) -> str:
        return f"Assinatura {self.assinatura_id}"
    
    def __repr__(self):
        return self.__str__()
    
   
    def get_queryset(self):
        try:
            query = self.request.data
            if query is not None:
                return Assinaturas.objects.all()
            else:
                return Response({"detail":query})
        except:
            return Response({"detail":"Error!"})
    
    def list(self, request):
        try:
            items = self.get_queryset()
            items = self.filter_queryset(items)
            items = self.paginate_queryset(items)
            if items:
                serialized_items = AssinaturaSerializer(items, many=True)
                return Response(serialized_items.data)
            else:
                return Response({"detail":"Not Found!"})
        except:
            return Response({"detail":"Error List"})
    
    def get_object(self, request):
        item = self.get_queryset()
        filter = {}
        for field in self.multiple_lookup_fields:
            filter[field] = self.kwargs[field]

        obj = get_object_or_404(item, **filter)
        self.check_object_permissions(self.request, obj)
        return obj
    
    def perform_create(self, serializer):
        permission_classes = [IsAuthenticated]
        serializer.save(user=self.request.user)
    
    def perform_update(self, serializer):
        permission_classes = [IsAuthenticated]
        instance = serializer.save()
    
    def perform_destroy(self, instance):
        permission_classes = [IsAuthenticated]
        instance = instance.destroy()

class AcessosFilter(django_filters.FilterSet):

    class Meta:
        model = Acessos
        fields = {
            'acesso_data': ('lte', 'gte'),
            'assinante__nome': ['contains'],
            'assinante__sobrenome': ['contains'],
            'assinante__email': ['contains'],
            'assinante__razao_social': ['contains'],
            'assinante__nome_fantasia': ['contains'],
            'assinante__regiao__bairro': ['contains'],
            'assinante__regiao__cidade': ['contains'],
            'assinante__regiao__estado': ['contains'],
            'assinante__estado_civil__estado_civil': ['contains'],
        }

#class AcessosView(generics.ListCreateAPIView, mixins.CreateModelMixin, mixins.UpdateModelMixin, 
#                     mixins.DestroyModelMixin, BasePermission):
class AcessosView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = AcessoSerializer
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = AcessosFilter
    search_fields=['acesso_data', 'assinante__nome', 'assinante__sobrenome','assinante__nome_fantasia', 
                   'assinante__razao_social', 'assinante__regiao__bairro','assinante__regiao__cidade','assinante__regiao__estado',
                   'assinante__estado_civil__estado_civil']
    ordering_fields = ['acesso_id', 'acesso_data']
    ordering = ['acesso_id']
    pagination_class = SetPagination
    name = "Acessos"
    description = "Acessos EndPoint"
    
    
    
    def __str__(self) -> str:
        return f"Acesso {self.acesso_id}"
    
    def __repr__(self):
        return self.__str__()
    
   
    def get_queryset(self):
        try:
            query = self.request.data
            if query is not None:
                return Acessos.objects.all()
            else:
                return Response({"detail":query})
        except:
            return Response({"detail":"Error!"})
    
    def list(self, request):
        try:
            items = self.get_queryset()
            items = self.filter_queryset(items)
            items = self.paginate_queryset(items)
            if items:
                serialized_items = AcessoSerializer(items, many=True)
                return Response(serialized_items.data)
            else:
                return Response({"detail":"Not Found!"})
        except:
            return Response({"detail":"Error List"})
    
    def get_object(self, request):
        item = self.get_queryset()
        filter = {}
        for field in self.multiple_lookup_fields:
            filter[field] = self.kwargs[field]

        obj = get_object_or_404(item, **filter)
        self.check_object_permissions(self.request, obj)
        return obj
    
    def perform_create(self, serializer):
        permission_classes = [IsAuthenticated]
        serializer.save(user=self.request.user)
    
    def perform_update(self, serializer):
        permission_classes = [IsAuthenticated]
        instance = serializer.save()
    
    def perform_destroy(self, instance):
        permission_classes = [IsAuthenticated]
        instance = instance.destroy()
        

class PagamentosFilter(django_filters.FilterSet):
    min_valor = django_filters.NumberFilter(field_name="valor", lookup_expr='gte')
    max_valor = django_filters.NumberFilter(field_name="valor", lookup_expr='lte')

    class Meta:
        model = Pagamentos
        fields = {
            'pagamento_data': ('lte', 'gte'),
            'forma_pagamento__forma_pagamento': ['contains'],
            'status_pagamento__status_pagamento': ['contains'],
            'assinante__nome': ['contains'],
            'assinante__sobrenome': ['contains'],
            'assinante__email': ['contains'],
            'assinante__razao_social': ['contains'],
            'assinante__nome_fantasia': ['contains'],
            'assinante__regiao__bairro': ['contains'],
            'assinante__regiao__cidade': ['contains'],
            'assinante__regiao__estado': ['contains'],
            'assinante__estado_civil__estado_civil': ['contains'],
            'assinatura__plano__plano': ['contains'],
            'assinatura__status': ['exact'],
        }

#class PagamentosView(generics.ListCreateAPIView, mixins.CreateModelMixin, mixins.UpdateModelMixin, 
#                     mixins.DestroyModelMixin, BasePermission):
class PagamentosView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = PagamentoSerializer
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = PagamentosFilter
    search_fields=['forma_pagamento__forma_pagamento','status_pagamento__status_pagamento','assinatura__plano__plano','assinatura__status','assinante__nome',
                   'assinante__sobrenome','assinante__nome_fantasia', 'assinante__razao_social',
                   'assinante__regiao__bairro','assinante__regiao__cidade','assinante__regiao__estado','assinante__estado_civil__estado_civil']
    ordering_fields = ['pagamento_id', 'pagamento_data', 'valor']
    ordering = ['pagamento_id']
    pagination_class = SetPagination
    name = "Pagamentos"
    description = "Pagamentos EndPoint"

    
    
    def __str__(self) -> str:
        return f"Pagamento de {self.assinante_id} em {self.pagamento_data}"
    
    def __repr__(self):
        return self.__str__()
    
   
    def get_queryset(self):
        try:
            query = self.request.data
            if query is not None:
                return Pagamentos.objects.all()
            else:
                return Response({"detail":query})
        except:
            return Response({"detail":"Error!"})
    
    def list(self, request):
        try:
            items = self.get_queryset()
            items = self.filter_queryset(items)
            items = self.paginate_queryset(items)
            if items:
                serialized_items = PagamentoSerializer(items, many=True)
                return Response(serialized_items.data)
            else:
                return Response({"detail":"Not Found!"})
        except:
            return Response({"detail":"Error List"})
    
    """
    def get_object(self, request):
        item = self.get_queryset()
        filter = {}
        for field in self.multiple_lookup_fields:
            filter[field] = self.kwargs[field]

        obj = get_object_or_404(item, **filter)
        self.check_object_permissions(self.request, obj)
        return obj
    
    def perform_create(self, serializer):
        permission_classes = [IsAuthenticated]
        serializer.save(user=self.request.user)
    
    def perform_update(self, serializer):
        permission_classes = [IsAuthenticated]
        instance = serializer.save()
    
    def perform_destroy(self, instance):
        permission_classes = [IsAuthenticated]
        instance = instance.destroy()
    """


#class AssinanteView(generics.RetrieveUpdateDestroyAPIView):
class AssinanteView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Assinantes.objects.all()
    serializer_class = AssinanteSerializer
    name = "Assinante"
    description = "Assinante Endpoint"
    
    
#class AssinaturaView(generics.RetrieveUpdateDestroyAPIView):
class AssinaturaView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Assinaturas.objects.all()
    serializer_class = AssinaturaSerializer
    name = "Assinatura"
    description = "Assinatura Endpoint"
    
#class AcessoView(generics.RetrieveUpdateDestroyAPIView):
class AcessoView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Acessos.objects.all()
    serializer_class = AcessoSerializer
    name = "Acesso"
    description = "Acesso Endpoint"

#class PagamentoView(generics.RetrieveUpdateDestroyAPIView):
class PagamentoView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Pagamentos.objects.all()
    serializer_class = PagamentoSerializer
    name = "Pagamento"
    description = "Pagamento Endpoint"




class EstadosCivisView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = EstadosCivis.objects.all()
    serializer_class = EstadoCivilSerializer
    filter_backends = [django_filters.DjangoFilterBackend, filters.OrderingFilter]
    ordering = ['estado_civil_id']
    name = "Estados Civis"
    description = "Estados Civis Endpoint"
    
    
    
class FormasdePagamentoView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = FormasdePagamento.objects.all()
    serializer_class = FormadePagamentoSerializer
    filter_backends = [django_filters.DjangoFilterBackend, filters.OrderingFilter]
    ordering = ['forma_pagamento_id']
    name = "Formas de Pagamento"
    description = "Formas de Pagamento Endpoint"


class StatusPagamentoView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = StatusPagamento.objects.all()
    serializer_class = StatusPagamentoSerializer
    filter_backends = [django_filters.DjangoFilterBackend, filters.OrderingFilter]
    ordering = ['status_pagamento_id']
    name = "Status Pagamento"
    description = "Status Pagamento Endpoint"


class PlanosView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Planos.objects.all()
    serializer_class = PlanoSerializer
    filter_backends = [django_filters.DjangoFilterBackend, filters.OrderingFilter]
    ordering = ['plano_id']
    name = "Planos"
    description = "Planos Endpoint"


class RegioesView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Regioes.objects.all()
    serializer_class = RegiaoSerializer
    pagination_class = SetPagination
    filter_backends = [django_filters.DjangoFilterBackend, filters.OrderingFilter]
    ordering = ['regiao_id']
    name = "Regiões"
    description = "Regiões Endpoint"



class OportunidadesFilter(django_filters.FilterSet):

    class Meta:
        model = Oportunidades
        fields = {
            'id': ['exact'],
            'data': ('lte', 'gte'),
            'data_finalizacao': ('lte', 'gte'),
            'titulo': ['contains'],
            'consultor': ['contains'],
            'bairro': ['contains'],
            'cidade': ['contains'],
            'estado': ['contains'],
            'estado_civil': ['contains'],
            'profissao': ['contains'],
            'sexo': ['contains'],
            'renda': ['contains'],
            'idade': ('lte', 'gte'),
            'idade_range': ['contains'],
            'midia': ['contains'],
            'canal': ['contains'],
            'temperatura': ['contains'],
            'unidade': ['contains'],
            'unidade_email': ['contains'],
            'interesse': ['contains'],
            'categoria': ['contains'],
            'tipo': ['contains'],
            'status': ['contains'],
            'funil': ['contains'],
            'etapa_funil': ['contains'],
            'motivo_perda_pausa': ['contains'],
            'dias_finalizacao': ('lte', 'gte'),
            'finalizacao_range': ['contains'],
            'utm_source': ['contains'],
            'utm_medium': ['contains'],
        }



class OportunidadesView(generics.ListAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = OportunidadeSerializer
    filter_backends = [django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_class = OportunidadesFilter
    search_fields=['id','data','data_finalizacao','titulo','consultor','bairro','cidade','estado','estado_civil','profissao','sexo','renda','idade','idade_range','midia','canal','temperatura','unidade','unidade_email','interesse','categoria','tipo','status','funil','etapa_funil','motivo_perda_pausa','dias_finalizacao','finalizacao_range','utm_source','utm_medium','unidade_id','prediction','most_likely_outcome']
    ordering_fields = ['id', 'data', 'unidade']
    ordering = ['id']
    pagination_class = SetPagination
    name = "Oportunidades"
    description = "Oportunidades EndPoint"

    
    
    def __str__(self) -> str:
        return f"Oportunidade de {self.consultor}, {self.unidade} em {self.data}"
    
    def __repr__(self):
        return self.__str__()
    
   
    def get_queryset(self):
        try:
            query = self.request.data
            if query is not None:
                return Oportunidades.objects.all()
            else:
                return Response({"detail":query})
        except:
            return Response({"detail":"Error!"})
    
    def list(self, request):
        try:
            items = self.get_queryset()
            items = self.filter_queryset(items)
            items = self.paginate_queryset(items)
            if items:
                serialized_items = OportunidadeSerializer(items, many=True)
                return Response(serialized_items.data)
            else:
                return Response({"detail":"Not Found!"})
        except:
            return Response({"detail":"Error List"})


class OportunidadeView(generics.RetrieveAPIView):
    permission_classes = [IsAuthenticated]
    queryset = Oportunidades.objects.all()
    serializer_class = OportunidadeSerializer
    name = "Oportunidadde"
    description = "Oportunidade Endpoint"



class Prediction(APIView):
    permission_classes = [IsAuthenticated]
    def post(self, request):
        data = request.data
        id = data.get("id")
        oportunidade_id = data.get("id")
        queryset = Oportunidades.objects.filter(id=oportunidade_id)
        data_dict = list(queryset.values())
        #queryset = Oportunidades.objects.all()
        #column_data = queryset.values_list('etapa_funil', flat=True)
        #for value in column_data:
            #etapa_funil = value
            
        try:
            df_oportunidades = pd.DataFrame(data_dict)
            etapa_funil = str(df_oportunidades['etapa_funil'].values[0])
            if etapa_funil=="Lead/Prospecção":
                model = ApiConfig.model1
                next_step = "Qualificação"
            elif etapa_funil=="Qualificação":
                model = ApiConfig.model2
                next_step="1ª Reunião"
            elif etapa_funil=="1ª Reunião":
                model = ApiConfig.model3
                next_step="2ª Reunião"
            elif etapa_funil=="2ª Reunião":
                model = ApiConfig.model4
                next_step="Assinatura"
            elif etapa_funil=="Assinatura":
                model = ApiConfig.model5
                next_step="Recrutado"
            elif etapa_funil=="Recrutado":
                return Response({"Oportunidade":oportunidade_id, "Etapa Recrutado": "Última etapa alcançada. Não há como avançar."}, status=400)
            else:
                return Response({"Oportunidade":oportunidade_id, "Etapa Funil":etapa_funil,  "Erro": "Não foi possível utilizar a etapa de funil utilizada para esta oportunidade."}, status=400)
            #predict using independent variables
            PredictionMade = str(np.round(((model.predict(df_oportunidades).values[0]) * 100),2))
            response_dict = {"Oportunidade":str(id), "Etapa Funil Atual":etapa_funil, f"Probabilidade atingir etapa {next_step}": f"{PredictionMade}%"}
            print(response_dict)
            return Response(response_dict, status=200)
        
        except Exception as e:
            return Response({"Oportunidade_id":id, "Etapa_funil":str(etapa_funil), "Erro": str(e)}, status=400)










