import json

from django.http import Http404
from django.db.models import Q

from .models import Plant, EcologicalRegion, EcologicalDistrictLayer, SoilOrder, SoilVariant
from .utils import get_point_from_coordinates


def coordinate_filter(request, queryset, ignore_soil_order=False):
    coordinates = request.query_params.get('coordinates')

    if coordinates is not None:
        pnt = get_point_from_coordinates(coordinates)
        filtered_regions = EcologicalRegion.objects.filter(
            ecologicaldistrictlayer__geom__intersects=pnt).values_list('id', flat=True)
        filtered_soil_orders = SoilOrder.objects.filter(
            soillayer__geom__intersects=pnt).values_list('id', flat=True)

        # Filter by ecological regions and soil orders
        if ignore_soil_order:
            return queryset.filter(ecological_regions__in=filtered_regions).distinct()
        else:
            return queryset.filter(
                Q(ecological_regions__in=filtered_regions) &
                Q(soil_order__in=filtered_soil_orders)).distinct()

    return queryset


def soil_variant_filter(request, queryset):
    soil_variant = request.query_params.get('soilVariant')

    if soil_variant in {"D", "W", "M"}:
        soil_variant_ids = SoilVariant.objects.filter(Q(name__startswith=soil_variant) | Q(
            name__startswith="M")).values_list('id', flat=True).distinct()
        return queryset.filter(soil_variants__in=soil_variant_ids).distinct()

    return queryset


def zone_filter(zone_json, queryset):
    return queryset.filter(zones__id__contains=zone_json['id']).distinct()


def soil_order_coordinate_filter(coordinates):
    pnt = get_point_from_coordinates(coordinates)
    try:
        return SoilOrder.objects.filter(soillayer__geom__intersects=pnt)
    except SoilOrder.DoesNotExist:
        raise Http404(f"Soil Order cannot be found for point {pnt}")


def ecological_district_coordinate_filter(coordinates):
    pnt = get_point_from_coordinates(coordinates)
    try:
        return EcologicalDistrictLayer.objects.filter(geom__intersects=pnt)
    except EcologicalDistrictLayer.DoesNotExist:
        raise Http404(
            f"Ecological district layer cannot be found for point {pnt}")


def get_filtered_plants(request):
    filtered_plants = Plant.objects.all()

    zone = request.query_params.get('zone')
    if zone != None:
        zone_json = json.loads(zone)
        filtered_plants = zone_filter(zone_json, filtered_plants)

        if not zone_json['ignore_location_filter']:
            filtered_plants = coordinate_filter(
                request, filtered_plants, ignore_soil_order=zone_json['ignore_soil_order_filter'])
    else:
        filtered_plants = coordinate_filter(request, filtered_plants)

    filtered_plants = soil_variant_filter(request, filtered_plants)

    return filtered_plants
