from django.contrib.gis.geos import Point
from django.http import JsonResponse
from django.views.generic import TemplateView

from apps.core.forms.search import LocationSearchForm
from apps.core.services.location_search import (
    LocationSearchFilters,
    location_search_service,
)
from apps.parks.filters import ParkFilter
from apps.parks.models import Park


class AdaptiveSearchView(TemplateView):
    template_name = "core/search/results.html"

    def get_queryset(self):
        """
        Get the base queryset, optimized with select_related and prefetch_related
        """
        return Park.objects.select_related("operator", "property_owner").prefetch_related("location", "photos").all()

    def get_filterset(self):
        """
        Get the filterset instance
        """
        return ParkFilter(self.request.GET, queryset=self.get_queryset())

    def get_context_data(self, **kwargs):
        """
        Add filtered results and filter form to context
        """
        context = super().get_context_data(**kwargs)
        filterset = self.get_filterset()

        # Check if location-based search is being used
        location_search = self.request.GET.get("location_search", "").strip()
        near_location = self.request.GET.get("near_location", "").strip()

        # Add location search context
        context.update(
            {
                "results": filterset.qs,
                "filters": filterset,
                "applied_filters": bool(self.request.GET),  # Check if any filters are applied
                "is_location_search": bool(location_search or near_location),
                "location_search_query": location_search or near_location,
            }
        )

        return context


class FilterFormView(TemplateView):
    """
    View for rendering just the filter form for HTMX updates
    """

    template_name = "core/search/filters.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        filterset = ParkFilter(self.request.GET, queryset=Park.objects.all())
        context["filters"] = filterset
        return context


class LocationSearchView(TemplateView):
    """
    Enhanced search view with comprehensive location search capabilities.
    """

    template_name = "core/search/location_results.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Build search filters from request parameters
        filters = self._build_search_filters()

        # Perform search
        results = location_search_service.search(filters)

        # Group results by type for better presentation
        grouped_results = {
            "parks": [r for r in results if r.content_type == "park"],
            "rides": [r for r in results if r.content_type == "ride"],
            "companies": [r for r in results if r.content_type == "company"],
        }

        context.update(
            {
                "results": results,
                "grouped_results": grouped_results,
                "total_results": len(results),
                "search_filters": filters,
                "has_location_filter": bool(filters.location_point),
                "search_form": LocationSearchForm(self.request.GET),
            }
        )

        return context

    def _build_search_filters(self) -> LocationSearchFilters:
        """Build LocationSearchFilters from request parameters."""
        form = LocationSearchForm(self.request.GET)
        form.is_valid()  # Populate cleaned_data

        # Parse location coordinates if provided
        location_point = None
        lat = form.cleaned_data.get("lat")
        lng = form.cleaned_data.get("lng")
        if lat and lng:
            try:
                location_point = Point(float(lng), float(lat), srid=4326)
            except (ValueError, TypeError):
                location_point = None

        # Parse location types
        location_types = set()
        if form.cleaned_data.get("search_parks"):
            location_types.add("park")
        if form.cleaned_data.get("search_rides"):
            location_types.add("ride")
        if form.cleaned_data.get("search_companies"):
            location_types.add("company")

        # If no specific types selected, search all
        if not location_types:
            location_types = {"park", "ride", "company"}

        # Parse radius
        radius_km = None
        radius_str = form.cleaned_data.get("radius_km", "").strip()
        if radius_str:
            try:
                radius_km = float(radius_str)
                # Clamp between 1-500km
                radius_km = max(1, min(500, radius_km))
            except (ValueError, TypeError):
                radius_km = None

        return LocationSearchFilters(
            search_query=form.cleaned_data.get("q", "").strip() or None,
            location_point=location_point,
            radius_km=radius_km,
            location_types=location_types if location_types else None,
            country=form.cleaned_data.get("country", "").strip() or None,
            state=form.cleaned_data.get("state", "").strip() or None,
            city=form.cleaned_data.get("city", "").strip() or None,
            park_status=self.request.GET.getlist("park_status") or None,
            include_distance=True,
            max_results=int(self.request.GET.get("limit", 100)),
        )


class LocationSuggestionsView(TemplateView):
    """
    AJAX endpoint for location search suggestions.
    """

    def get(self, request, *args, **kwargs):
        query = request.GET.get("q", "").strip()
        limit = int(request.GET.get("limit", 10))

        if len(query) < 2:
            return JsonResponse({"suggestions": []})

        try:
            suggestions = location_search_service.suggest_locations(query, limit)
            return JsonResponse({"suggestions": suggestions})
        except Exception as e:
            return JsonResponse({"error": str(e)}, status=500)
