import json
from django.http import JsonResponse
from django.shortcuts import redirect
from django.db.models import Q, Count, Max, Min
from django.shortcuts import get_object_or_404, render
from developer.models import Developer
from development.forms import MasterDevelopmentEditForm, MasterDevelopmentTranslateEditForm
from development.models import Currency, Development, DevelopmentTranslate, ONHArea, ONHDistrict, ONHPostcode, ONHStation, ONHZone

from geo_location.models import City, Country, Location, LondonArea, LondonZone
from main.models import Language
from django.core.cache import cache
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.gis.geos import GEOSGeometry, Polygon
from main.utils import user_control
from user.utils import get_settings
# Create your views here.
CACHE_TIME = settings.CACHE_TIME

def map_data(request):
    kwargs = request.GET
    language = request.GET.get("language", "en")
    lang = Language.objects.filter(code=language).first()
    if lang is None:
        lang = Language.objects.filter(code="en").first()
    cache_key = f"map_data_{language}_{'_'.join(item for item in kwargs.values())}"
    cached_result = cache.get(cache_key)
    if cached_result:
        return cached_result
    currency = kwargs.get("currency", "GBP")
    try: default_currency = Currency.objects.get(code=currency)
    except: default_currency = Currency.objects.get(code="GBP")
    f = Q(is_active=True, is_deleted=False, geo_json__isnull=False, developer__is_active=True)
    if "featured" in kwargs and kwargs['featured'] == "true":
        f &= Q(is_featured=kwargs['featured']=="true")
    if "search" in kwargs:
        search = kwargs.get("search")
        search = search.replace("+", " ")
        search_list = search.split(" ")
        if len(search_list) > 1:
            search_list.append(search)
        s = dev_s = city_s = country_s =station_s = district_s = london_zone_s = london_area_s = london_zip_code_s = None
        for q in search_list:
            if s is None: s = Q(title__icontains=q) | Q(translates__title__icontains=q) | Q(slug__icontains=q) | Q(translates__slug__icontains=q)
            else: s |= Q(title__icontains=q) | Q(translates__title__icontains=q) | Q(slug__icontains=q) | Q(translates__slug__icontains=q)
            if dev_s is None: dev_s = Q(slug__icontains=q) | Q(translates__slug__icontains=q) | Q(name__icontains=q) | Q(translates__name__icontains=q)
            else: dev_s |= Q(slug__icontains=q) | Q(translates__slug__icontains=q) | Q(name__icontains=q) | Q(translates__name__icontains=q)
            if city_s is None: city_s = Q(slug__icontains=q) | Q(translates__slug__icontains=q) | Q(name__icontains=q) | Q(translates__name__icontains=q)
            else: city_s |= Q(slug__icontains=q) | Q(translates__slug__icontains=q) | Q(name__icontains=q) | Q(translates__name__icontains=q)
            if country_s is None: country_s = Q(slug__icontains=q) | Q(translates__slug__icontains=q) | Q(name__icontains=q) | Q(translates__name__icontains=q) | Q(code__icontains=q)
            else: country_s |= Q(slug__icontains=q) | Q(translates__slug__icontains=q) | Q(name__icontains=q) | Q(translates__name__icontains=q) | Q(code__icontains=q)
            if station_s is None: station_s = Q(slug__icontains=q) | Q(name__icontains=q)
            else: station_s |= Q(slug__icontains=q) | Q(name__icontains=q)
            if district_s is None: district_s = Q(slug__icontains=q) | Q(name__icontains=q)
            else: district_s |= Q(slug__icontains=q) | Q(name__icontains=q)
            if london_zone_s is None: london_zone_s = Q(slug__icontains=q) | Q(name__icontains=q)
            else: london_zone_s |= Q(slug__icontains=q) | Q(name__icontains=q)
            if london_area_s is None: london_area_s = Q(slug__icontains=q) | Q(name__icontains=q)
            else: london_area_s |= Q(slug__icontains=q) | Q(name__icontains=q)
            if london_zip_code_s is None: london_zip_code_s = Q(slug__icontains=q) | Q(name__icontains=q)
            else: london_zip_code_s |= Q(slug__icontains=q) | Q(name__icontains=q)
        if dev_s is not None:
            s_developer = Developer.objects.filter(dev_s).distinct()
            if s is None: s = Q(developer__in=s_developer)
            else: s |= Q(developer__in=s_developer)
        if city_s is not None:
            s_city = City.objects.filter(city_s).distinct()
            if s is None: s = Q(city__in=s_city)
            else: s |= Q(city__in=s_city)
        if country_s is not None:
            s_country = Country.objects.filter(country_s).distinct()
            if s is None: s = Q(country__in=s_country)
            else: s |= Q(country__in=s_country)
        if station_s is not None:
            s_station = ONHStation.objects.filter(station_s).distinct()
            if s is None: s = Q(onh_station__in=s_station)
            else: s |= Q(onh_station__in=s_station)
        if district_s is not None:
            s_district = ONHDistrict.objects.filter(district_s).distinct()
            if s is None: s = Q(onh_district__in=s_district)
            else: s |= Q(onh_district__in=s_district)
        if london_zip_code_s is not None:
            s_london_zip_code = ONHPostcode.objects.filter(london_zip_code_s).distinct()
            if s is None: s = Q(onh_postcode__in=s_london_zip_code)
            else: s |= Q(onh_postcode__in=s_london_zip_code)
        location_s = None
        if london_zone_s is not None:
            s_london_zone = ONHZone.objects.filter(london_zone_s).distinct()
            if s is None: s = Q(onh_postcode__in=s_london_zone)
            else: s |= Q(onh_postcode__in=s_london_zone)
        if london_area_s is not None:
            s_london_area = ONHArea.objects.filter(london_area_s).distinct()
            if s is None: s = Q(onh_postcode__in=s_london_area)
            else: s |= Q(onh_postcode__in=s_london_area)
        if location_s is not None:
            s_location = Location.objects.filter(location_s).distinct()
            if s is None: s = Q(location__in=s_location)
            else: s |= Q(location__in=s_location)
            
        
        if s is not None: f &= s
    if "developer" in kwargs:
        developer = kwargs.get("developer")
        developer = developer.split(",")
        f &= Q(developer__slug__in=developer) | Q(developer__translates__slug__in=developer)
    if "city" in kwargs:
        city = kwargs.get("city")
        city = city.replace("city-","")
        city = city.split(",")
        f &= Q(city__slug__in=city) | Q(city__translates__slug__in=city)
    if "country" in kwargs:
        country = kwargs.get("country")
        country = country.replace("country-","")
        country = country.split(",")
        f &= Q(country__slug__in=country) | Q(country__translates__slug__in=country)
    if "pay_opt" in kwargs:
        payment_options = kwargs.get("pay_opt")
        payment_options = payment_options.replace("pay_opt-", "")
        payment_options = payment_options.split(",")
        f &= Q(payment_option__slug__in=payment_options)
        
    if "pay_plan" in kwargs:
        payment_plans = kwargs.get("pay_plan")
        payment_plans = payment_plans.replace("pay_plan-", "")
        payment_plans = payment_plans.split(",")
        f &= Q(payment_plan__slug__in=payment_plans)
    if "key_feature" in kwargs:
        key_features = kwargs.get("key_feature")
        key_features = key_features.replace("key_feature-", "")
        key_features = key_features.split(",")
        f &= Q(key_features__feature__slug__in=key_features)
    if "bedroom" in kwargs:
        bedrooms = kwargs.get("bedroom")
        bedrooms = bedrooms.replace("bedroom-", "")
        bedrooms = bedrooms.split(",")
        f &= Q(flats__bedrooms_num__in=bedrooms)
    if "priceMin" in kwargs:
        try:price_from = float(kwargs.get("priceMin"))
        except: price_from = 0
        f &= Q(flats__base_price__gt=0)
        if default_currency.code == "GBP":
            p1 = price_from / default_currency.aed_rate
            f &= Q(default_currency=default_currency, flats__base_price__gte=price_from) | Q(default_currency__code="AED", flats__base_price__gte=p1)
            
        elif default_currency.code == "AED":
            p1 = price_from / default_currency.gbp_rate
            f &= Q(default_currency=default_currency, flats__base_price__gte=price_from) | Q(default_currency__code="GBP", flats__base_price__gte=p1)
        else:
            p1 = price_from / default_currency.aed_rate
            p2 = price_from / default_currency.gbp_rate
            f &= Q(default_currency__code="AED", flats__base_price__gte=price_to) | Q(default_currency__code="GBP", flats__base_price__gte=p2)
    if "priceMax" in kwargs:
        try: price_to = float(kwargs.get("priceMax"))
        except: price_to = 0
        f &= Q(flats__base_price__gt=0)
        if default_currency.code == "GBP":
            p1 = price_to / default_currency.aed_rate
            f &= Q(default_currency=default_currency, flats__base_price__lte=price_to) | Q(default_currency__code="AED", flats__base_price__lte=p1)
        elif default_currency.code == "AED":
            p1 = price_to / default_currency.gbp_rate
            f &= Q(default_currency=default_currency, flats__base_price__lte=price_to) | Q(default_currency__code="GBP", flats__base_price__lte=p1)
        else:
            p1 = price_to / default_currency.aed_rate
            p2 = price_to / default_currency.gbp_rate
            f &= Q(default_currency__code="AED", flats__base_price__lte=price_to) | Q(default_currency__code="GBP", flats__base_price__lte=p2)
    if "district" in kwargs:
        district = kwargs.get("district")
        district = district.replace("district-","")
        district = district.split(",")
        f &= Q(onh_district__slug__in=district)
    if "zone" in kwargs:
        london_zone = kwargs.get("zone")
        london_zone = london_zone.split(",")
        f &= Q(location__london_zone__slug__in=london_zone)
    if "area" in kwargs:
        london_area = kwargs.get("area")
        london_area = london_area.replace("area-","")
        london_area =  london_area.split(",")
        f &= Q(location__london_area__slug__in=london_area)
    if "zipcode" in kwargs:
        london_zip_code = kwargs.get("zipcode")
        london_zip_code = london_zip_code.replace("zipcode-", "")
        london_zip_code = london_zip_code.split(",")
        f &= Q(onh_postcode__slug__in=london_zip_code)
    if "completionDate" in kwargs:
        completion_date = kwargs.get("completionDate")
        completion_date = completion_date.split(",")
        if "ready-to-move" in completion_date:
            completion_date.remove("ready-to-move")
            f &= Q(is_ready_to_move=True) | Q(completed_at__year__in=completion_date)
        else:
            f &= Q(completed_at__year__in=completion_date)
    if "postCode" in kwargs:
        post_code = kwargs.get("postCode")
        post_code = post_code.split(",")
        f &= Q(location__post_code__out_code__in=post_code)
    if "region" in kwargs:
        region = kwargs.get("region")
        region = region.split(",")
        f &= Q(location__post_code__region__slug__in=region)
    if "station" in kwargs:
        station = kwargs.get("station")
        station = station.replace("station-","")
        station = station.split(",")
        f &= Q(onh_station__slug__in=station)
    if "trainStation" in kwargs:
        train_station = kwargs.get("trainStation")
        train_station = train_station.split(",")
        f &= Q(public_facilities__public_facility__slug__in=train_station, public_facilities__public_facility__type_id=3)
    if "busStation" in kwargs:
        bus_station = kwargs.get("busStation")
        bus_station = bus_station.split(",")
        f &= Q(public_facilities__public_facility__slug__in=bus_station, public_facilities__public_facility__type_id=4)
    if "available" in kwargs and kwargs['available'] == "true":
        is_sold_out = kwargs.get("available") == "false"
        f &= Q(is_sold_out=is_sold_out)
    if "readyToMove" in kwargs and kwargs['readyToMove'] == "true":
        ready_to_move = kwargs.get("readyToMove") == "true"
        f &= Q(is_ready_to_move=ready_to_move)
    if "polygon" in kwargs:
        polygon = kwargs.get("polygon")
        # create a polygon from the polygon string and check if the point is inside the polygon
        coordinates = json.loads(polygon)
        if coordinates[0] != coordinates[-1]:
            coordinates.append(coordinates[0])
        polygon_obj = Polygon(coordinates)
        f &= Q(coordinates__within=polygon_obj)
    developments = Development.objects.filter(f).order_by("is_sold_out").distinct()
    geojson = list(developments.values_list("geo_json", flat=True))
    result = JsonResponse({"type": "FeatureCollection","crs": {"type": "name","properties": {"name": "EPSG:4326"}},"features": geojson}, content_type='application/geojson', safe=False)
    cache.set(cache_key, result, CACHE_TIME)
    return result


@login_required
def master_developments(request, country=None, city=None):
    user_controller = user_control(request)
    if not user_controller['has_perm']:
        return redirect(user_controller['redirect_uri'])
    site_settings = get_settings(request)
    if site_settings.page_name in ["", None, "None"]:
        site_settings.page_name = "Development List"
    page_adr = f"{site_settings.theme_name}/developments.html"
    base_adr = f"{site_settings.theme_name}/base.html"
    developments = Development.objects.all()
    return render(request, page_adr, locals())

@login_required
def master_development(request, id):
    user_controller = user_control(request)
    if not user_controller['has_perm']:
        return redirect(user_controller['redirect_uri'])
    site_settings = get_settings(request)
    if site_settings.page_name in ["", None, "None"]:
        site_settings.page_name = "Development Details"
    development = get_object_or_404(Development, id=id)
    site_settings.page_name = f"{development.title} Details"
    languages = Language.objects.all()
    translates = DevelopmentTranslate.objects.filter(development=development)
    forms = []
    form = None
    for translate in translates:
        form = MasterDevelopmentTranslateEditForm(instance=translate)
        dir = '' if translate.language.code in ["en", "ru"] else 'dir-rtl'
        forms.append({"language":f"{translate.language.name}", "id":translate.id, 'dir':dir, "form":form})
    page_adr = f"{site_settings.theme_name}/development.html"
    base_adr = f"{site_settings.theme_name}/base.html"
    return render(request, page_adr, locals())

def master_development_edit_form(request, id):
    user_controller = user_control(request)
    if not user_controller['has_perm']:
        return redirect(user_controller['redirect_uri'])
    site_settings = get_settings(request)
    if site_settings.page_name in ["", None, "None"]:
        site_settings.page_name = "Development Edit"
    form = None
    try:
        country = Development.objects.get(id=id)
        form = MasterDevelopmentEditForm(instance=country)
        title = f"Edit Development: {country.name}"
    except Exception as e:
        title = "Edit Development"
    modal_id = "MasterEdit"
    btn_footer_value = "Edit"
    form_url = f"/master/developments/{id}/edit/"
    page_adr = f"{site_settings.theme_name}/modal.html"
    base_adr = f"{site_settings.theme_name}/base.html"
    return render(request, page_adr, locals())

def master_development_edit(request, id):
    user_controller = user_control(request)
    if not user_controller['has_perm']:
        return redirect(user_controller['redirect_uri'])
    site_settings = get_settings(request)
    if site_settings.page_name in ["", None, "None"]:
        site_settings.page_name = "Development Edit"
    development = get_object_or_404(Development, id=id)
    form = MasterDevelopmentEditForm(request.POST, instance=development)
    try:
        if form.is_valid():
            form.save()
            return JsonResponse({"success": True, "message": "Edit is success.", 'errors': [], 'results':[]})
        else:
            return JsonResponse({"success": False, "message": "error", 'errors': form.errors, 'results':[]})
    except:
        return JsonResponse({"success": False, "message": "not Found", 'errors': [], 'results':[]})
    
def master_development_text_edit(request, id):
    user_controller = user_control(request)
    if not user_controller['has_perm']:
        return redirect(user_controller['redirect_uri'])
    site_settings = get_settings(request)
    if site_settings.page_name in ["", None, "None"]:
        site_settings.page_name = "Development Edit"
    development = get_object_or_404(DevelopmentTranslate, id=id)
    form = MasterDevelopmentTranslateEditForm(request.POST, instance=development)
    try:
        if form.is_valid():
            form.save()
            return JsonResponse({"success": True, "message": "Edit is success.", 'errors': [], 'results':[]})
        else:
            return JsonResponse({"success": False, "message": "error", 'errors': form.errors, 'results':[]})
    except:
        return JsonResponse({"success": False, "message": "not Found", 'errors': [], 'results':[]})

@login_required
def master_developments_list(request, country=None, city=None):
    user_controller = user_control(request)
    if not user_controller['has_perm']:
        return redirect(user_controller['redirect_uri'])
    draw = request.GET.get('draw',1)
    if request.method == 'POST':
        draw = request.POST.get('draw',1)
        start = request.POST.get('start', 0)
        length = request.POST.get('length',10)
        search = request.POST.get('search[value]')
        order_column = request.POST.get('order[0][column]', "0")
        order_dir = request.POST.get('order[0][dir]', "desc")
        order_by = ""
        if order_column: 
            if order_column == "0": order_by = "id"
            elif order_column == "1": order_by = "title"
            elif order_column == "2": order_by = "slug"
            elif order_column == "3": order_by = "country__name"
            elif order_column == "4": order_by = "city__name"
            if order_dir == "desc": order_by = f"-{order_by}"
        try: length = int(length)
        except: length = 10
        try: start = int(start)
        except: start = 0

        obj = Development.objects.all()
        if country:
            obj = obj.filter(country_id=country)
        if city:
            obj = obj.filter(city_id=city)
        if search is not None:
            obj = obj.filter(Q(title__icontains=search) | Q(slug__icontains=search))

        obj = obj.order_by(order_by)

        serializer = MasterDevelopmentSerializer(obj[start:start+length], many=True)

        result = {
            "draw": draw,
            "recordsTotal": obj.count(),
            "recordsFiltered": obj.count(),
            "data": serializer.data
            }
        return JsonResponse(result)
    draw = request.GET.get('draw',1)
    return JsonResponse({"draw": draw,"recordsTotal": 0,"recordsFiltered": 0,"data": []})

