from .serializers import UserRelationDocumentSerializer
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from rest_framework.pagination import LimitOffsetPagination
from apps.search.document.user_document import UserRelationDocument
from django.http.response import HttpResponse
from rest_framework.response import Response
from apps.authentication.models import User
from rest_framework.views import APIView
from elasticsearch_dsl.query import Q
import abc


class PaginatedElasticSearchApiView(APIView, LimitOffsetPagination):
    """Base ApiView Class for elasticsearch views with pagination,
    Other ApiView classes should inherit from this class"""
    serializer_class = None
    document_class = None

    @abc.abstractmethod
    def generate_q_expression(self, query):
        """This method should be overridden
        and return a Q() expression."""

    def get(self, request, query):
        try:
            q = self.generate_q_expression(query)
            search = self.document_class.search().query(q)
            response = search.execute()

            print(f"Found {response.hits.total.value} hit(s) for query: '{query}'")

            results = self.paginate_queryset(response, request, view=self)  # noqa
            serializer = self.serializer_class(results, many=True)
            return self.get_paginated_response(serializer.data)
        except Exception as e:
            return HttpResponse(e, status=500)


class SearchUserDocumentApiView(PaginatedElasticSearchApiView):
    """Base ApiView Class for elasticsearch views with pagination,
    Other ApiView classes should inherit from this class"""
    serializer_class = UserRelationDocumentSerializer
    document_class = UserRelationDocument

    def generate_q_expression(self, query):
        return Q(
            'bool',
            should=[
                Q("match", user__username=query),
                Q("match", user__mobile=query),
                Q("match", user__national_code=query),
                Q("match", organization__type__key=query),
                Q("match", organization__name=query),
                Q("match", organization__city__name=query),
                Q("match", organization__province__name=query),
                Q("match", organization__national_unique_id=query),
                Q("match", organization__company_code=query),
                Q("match", role__role_name=query),
            ],
            minimum_should_match=1,
        )
