from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from django.db.models import Q
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi

from api.property_api.property.models.property import Property
from producers_products.models.producers_products import ProducersProducts
from service.models.services import Services
from jobs_company.models.jobs import Jobs

from api.property_api.property.serializers.property_serializer import PropertySerializer
from producers_products.serializers.producers_products_serializer import ProducersProductsSerializer
from service.serializers.services_serializer import ServiceSerializer
from jobs_company.serializers.jobs_serializer import JobsSerializer

from common.pagination.custom_pagination import CustomPageNumberPagination


class GlobalSearchView(ListAPIView):
    """
    Unified search for properties, products, services, and jobs.
    Optional `type` filter allows searching in a specific model only.
    """
    pagination_class = CustomPageNumberPagination

    @swagger_auto_schema(manual_parameters=[
        openapi.Parameter('search', openapi.IN_QUERY, description="Search text", type=openapi.TYPE_STRING),
        openapi.Parameter('type', openapi.IN_QUERY, description="Optional type filter: property, product, service, job", type=openapi.TYPE_STRING),
        openapi.Parameter('country', openapi.IN_QUERY, description="Country name", type=openapi.TYPE_STRING),
        openapi.Parameter('city', openapi.IN_QUERY, description="City name", type=openapi.TYPE_STRING),
        openapi.Parameter('state', openapi.IN_QUERY, description="State name", type=openapi.TYPE_STRING),
        openapi.Parameter('min_price', openapi.IN_QUERY, description="Minimum price (for properties)", type=openapi.TYPE_NUMBER),
        openapi.Parameter('max_price', openapi.IN_QUERY, description="Maximum price (for properties)", type=openapi.TYPE_NUMBER),
        openapi.Parameter('property_type', openapi.IN_QUERY, description="Property type (Buy, Sale, Rent)", type=openapi.TYPE_STRING),
    ])
    def get(self, request, *args, **kwargs):
        search = request.query_params.get("search")
        search_type = request.query_params.get("type")  # optional: property, product, service, job
        country = request.query_params.get("country")
        city = request.query_params.get("city")
        state = request.query_params.get("state")
        min_price = request.query_params.get("min_price")
        max_price = request.query_params.get("max_price")
        property_type = request.query_params.get("property_type")

        combined_results = []

        # -------- PROPERTY --------
        normalized_type = (search_type or "").strip().lower()

        if not normalized_type or normalized_type in {"properties", "property"}:
            property_qs = Property.objects.filter(is_active=True)
            if search:
                property_qs = property_qs.filter(Q(name__icontains=search) | Q(address__icontains=search))
            if country:
                property_qs = property_qs.filter(country__name__icontains=country)
            if city:
                property_qs = property_qs.filter(city__name__icontains=city)
            if state:
                property_qs = property_qs.filter(state__name__icontains=state)
            if min_price:
                property_qs = property_qs.filter(per_sqr_ft_price__gte=min_price)
            if max_price:
                property_qs = property_qs.filter(per_sqr_ft_price__lte=max_price)
            if property_type:
                property_qs = property_qs.filter(listed_for__iexact=property_type)

            property_data = PropertySerializer(property_qs, many=True, context={'request': request}).data
            for item in property_data:
                item["type"] = "property"
            combined_results += property_data

        # -------- PRODUCT --------
        if not normalized_type or normalized_type in {"producers", "producer", "products", "product"}:
            product_qs = ProducersProducts.objects.filter(is_active=True)
            if search:
                product_qs = product_qs.filter(Q(name__icontains=search) | Q(description__icontains=search))
            if country:
                product_qs = product_qs.filter(country__icontains=country)
            if city:
                product_qs = product_qs.filter(city__name__icontains=city)

            product_data = ProducersProductsSerializer(product_qs, many=True, context={'request': request}).data
            for item in product_data:
                item["type"] = "producer"
            combined_results += product_data

        # -------- SERVICE --------
        if not normalized_type or normalized_type in {"services", "service"}:
            service_qs = Services.objects.filter(is_active=True).select_related(
                "company",
                "category_services",
                "city",
                "city__state",
                "city__state__country",
            )
            if search:
                service_qs = service_qs.filter(
                    Q(name__icontains=search)
                    | Q(company__name__icontains=search)
                    | Q(category_services__name__icontains=search)
                )
            if country:
                service_qs = service_qs.filter(
                    Q(country__icontains=country)
                    | Q(city__state__country__name__icontains=country)
                )
            if city:
                service_qs = service_qs.filter(
                    Q(city__name__icontains=city)
                    | Q(state__icontains=city)
                )
            if state:
                service_qs = service_qs.filter(
                    Q(state__icontains=state)
                    | Q(city__state__name__icontains=state)
                )

            service_data = ServiceSerializer(service_qs, many=True, context={'request': request}).data
            for item in service_data:
                item["type"] = "service"
            combined_results += service_data

        # -------- JOB --------
        if not normalized_type or normalized_type in {"jobs", "job"}:
            job_qs = Jobs.objects.filter(is_active=True)
            if search:
                job_qs = job_qs.filter(Q(title__icontains=search) | Q(description__icontains=search))
            if country:
                job_qs = job_qs.filter(country__icontains=country)
            if city:
                job_qs = job_qs.filter(city__name__icontains=city)

            job_data = JobsSerializer(job_qs, many=True, context={'request': request}).data
            for item in job_data:
                item["type"] = "job"
            combined_results += job_data

        # -------- PAGINATION --------
        paginator = self.pagination_class()
        page = paginator.paginate_queryset(combined_results, request, view=self)
        if page is not None:
            return paginator.get_paginated_response(page)

        return Response(combined_results)
