
import sys
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from app_venin_web_new1.filters import *
from app_venin_web_new1.views.base.base_search_view import BaseSearchView
from app_venin_web_new1.serializers import (ArticulosSerializer, PreciosSerializer, EstrategiaLiberacionReadSerializer,
                                            CaracteristicaSerializer, PersonalSerializer, FacturaSerializer,
                                            CotizacionReadSerializer,NumeroSerializer)
from rest_framework.response import Response
from rest_framework.views import APIView 
from rest_framework import status
from rest_framework.decorators import api_view



#Search endpoint
@api_view(['POST'])
def Search(request,clase):
    data=request.data
    top=int(data['top'])
    opcion=data['opcion']
    scale='-'+opcion if data['scale']=='DESC' else opcion
    linea={'idclase':data['clase']}
    subclase={'idsubcla':data['subclase']}
    subgrupo={'clase3':data['subgrupo']}
    dictquery = {}
    if not data['clase']==0 and not data['clase']=='0':
        dictquery.update(linea)
    if not data['subclase']==0 and not data['subclase']=='0':
        dictquery.update(subclase)
    if not data['subgrupo']==0 and not data['subgrupo']=='0':
        dictquery.update(subgrupo)
    if not data['codigo']=="":
        dictquery.update({'codpro__icontains':data['codigo']})
    if not data['nombre']=="":
        dictquery.update({'nombre__icontains':data['nombre']})
    
    print(dictquery)
    Clase = getattr(sys.modules[__name__], clase)
    Serializer = getattr(sys.modules[__name__], clase+'Serializer')
    try:
        if not len(data) > 0:
            raise Exception
        else:
            queryset = Clase.objects.filter(**dictquery).order_by(scale)[:top]
            
            serializer = Serializer(queryset,many=True)
            return Response(serializer.data)
        
    except Exception as e:
        raise e
 

@api_view(["POST"])
def search_articulos(request):
    data = request.data

    # Validar si 'top' y 'opcion' están en el request
    try:
        top = int(data.get("top", 10))  # Si no se envía, por defecto 10
        opcion = data.get("opcion", "id")  # Por defecto ordena por ID
        scale = "-" + opcion if data.get("scale") == "DESC" else opcion
    except ValueError:
        raise ValueError("El parámetro 'top' debe ser un número.")

    # Aplicar filtros usando django-filters
    queryset = ArticuloFilter(data, queryset=Articulos.objects.all()).qs

    if queryset is None:
        raise ValueError("Error en el filtrado de artículos.")

    if not queryset.exists():
        return Response({"message": "No se encontraron artículos.", "status": "warning"}, 
                        status=status.HTTP_404_NOT_FOUND)

    # Aplicar orden y limitar resultados
    queryset = queryset.order_by(scale)[:top]

    # Serializar y devolver la respuesta
    serializer = ArticulosSerializer(queryset, many=True)
    return Response({"message": "success", "data": serializer.data}, status=status.HTTP_200_OK)


@api_view(["POST"])
def search_precios(request):
    data = request.data

    # Validar si 'top' y 'opcion' están en el request
    try:
        top = int(data.get("top", 10))  # Por defecto 10
        opcion = data.get("opcion", "id")  # Ordena por 'id' si no se especifica
        scale = "-" + opcion if data.get("scale") == "DESC" else opcion
    except ValueError:
        return Response({"message": "El parámetro 'top' debe ser un número.", "status": "error"}, 
                        status=status.HTTP_400_BAD_REQUEST)

    # Aplicar filtros usando django-filters
    queryset = PrecioFilter(data, queryset=Precios.objects.all()).qs

    if queryset is None:
        return Response({"message": "Error en el filtrado de precios.", "status": "error"}, 
                        status=status.HTTP_400_BAD_REQUEST)

    if not queryset.exists():
        return Response({"message": "No se encontraron precios.", "status": "warning"}, 
                        status=status.HTTP_404_NOT_FOUND)

    # Aplicar orden y limitar resultados
    queryset = queryset.order_by(scale)[:top]

    # Serializar y devolver la respuesta
    serializer = PreciosSerializer(queryset, many=True)
    return Response({"message": "success", "data": serializer.data}, status=status.HTTP_200_OK)


@api_view(["POST"])
def search_estrategias(request):
    data = request.data

    # Validar si 'top' y 'opcion' están en el request
    try:
        top = int(data.get("top", 10))  # Si no se envía, por defecto 10
        opcion = data.get("opcion", "idestrategia")  # Por defecto ordena por ID
        scale = "-" + opcion if data.get("scale") == "DESC" else opcion
    except ValueError:
        raise ValueError("El parámetro 'top' debe ser un número.")

    # Aplicar filtros usando django-filters
    queryset = EstrategiaFilter(data, queryset=EstrategiaLiberacion.objects.all()).qs

    if queryset is None:
        raise ValueError("Error en el filtrado de artículos.")

    if not queryset.exists():
        return Response({"message": "No se encontraron artículos.", "status": "warning"}, 
                        status=status.HTTP_404_NOT_FOUND)

    # Aplicar orden y limitar resultados
    queryset = queryset.order_by(scale)[:top]

    # Serializar y devolver la respuesta
    serializer = EstrategiaLiberacionReadSerializer(queryset, many=True)
    return Response({"message": "success", "data": serializer.data}, status=status.HTTP_200_OK)


@api_view(["POST"])
def search_caracteristicas(request):
    data = request.data

    # Validar si 'top' y 'opcion' están en el request
    try:
        top = int(data.get("top", 10))  # Si no se envía, por defecto 10
        opcion = data.get("opcion", "idcaracteristica")  # Por defecto ordena por ID
        scale = "-" + opcion if data.get("scale") == "DESC" else opcion
    except ValueError:
        raise ValueError("El parámetro 'top' debe ser un número.")

    # Aplicar filtros usando django-filters
    queryset = CaracteristicaFilter(data, queryset=Caracteristica.objects.all()).qs

    if queryset is None:
        raise ValueError("Error en el filtrado de artículos.")

    if not queryset.exists():
        return Response({"message": "No se encontraron artículos.", "status": "warning"}, 
                        status=status.HTTP_404_NOT_FOUND)

    # Aplicar orden y limitar resultados
    queryset = queryset.order_by(scale)[:top]

    # Serializar y devolver la respuesta
    serializer = CaracteristicaSerializer(queryset, many=True)
    return Response({"message": "success", "data": serializer.data}, status=status.HTTP_200_OK)


class SearchPersonalView(BaseSearchView):
    model = Personal
    serializer_class = PersonalSerializer
    ordering_field = "nombre"

    def get_queryset(self, request):
        text = request.data.get("text", "").strip()
        queryset = self.model.objects.all()
        if text:
            queryset = queryset.filter(nombre__icontains=text)
        return queryset


class SearchFactura(APIView):
    def get_object(self, dictquery):
        try:
            factura = Factura.objects.exclude(documen='NCR').get(**dictquery)
            serializer = FacturaSerializer(factura)
            return serializer.data
        except ObjectDoesNotExist:
            return None
        except MultipleObjectsReturned:
            raise Exception("Se encontraron múltiples facturas con los mismos criterios.")
        except Exception as e:
            raise e

    def post(self, request, format=None):
        data = request.data
        filter_params = {
            key: value for key, value in data.items()
            if key not in ['fecini', 'fecfin', 'tipofecha'] and value not in [None, '', 0]
        }

        if (
            'fecini' in data and data['fecini']
            and 'fecfin' in data and data['fecfin']
            and 'tipofecha' in data and data['tipofecha']
        ):
            tipofecha = data['tipofecha']
            filter_params[tipofecha + '__range'] = (data['fecini'], data['fecfin'])

        result = self.get_object(filter_params)
        if not result:
            return Response({"status": "error", "message": "No existen coincidencias."})
        return Response({"status": "success", "data": result})
  

class SearchCotizacion(APIView):
    def post(self, request):
        queryset = CotizacionFilter(request.data, queryset=Cotizacion.objects.all()).qs
        serializer = CotizacionReadSerializer(queryset, many= True)
        return Response(serializer.data)

                        
@api_view(['POST'])
def numeroSearch(request):
    try:
        serie = request.data['serie']    
        tipodoc = request.data['clasedoc']
        query = Numero.objects.get(serie=serie,clasedoc=tipodoc)   
        serializer = NumeroSerializer(query)
        return Response(serializer.data)
        
    except Exception as e:
        return Response({"message":"Dato no encontrado."},status=status.HTTP_400_BAD_REQUEST)
    
      