"""
Data entry view for satellite points.
"""
import json
import re
from datetime import datetime

from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Q
from django.http import JsonResponse
from django.shortcuts import render
from django.views import View

from ..models import ObjItem, Satellite


class DataEntryView(LoginRequiredMixin, View):
    """
    View for data entry form with Tabulator table.
    """
    
    def get(self, request):
        # Get satellites that have points
        satellites = Satellite.objects.filter(
            parameters__objitem__isnull=False
        ).distinct().order_by('name')
        
        context = {
            'satellites': satellites,
            "full_width_page": True
        }
        
        return render(request, 'mainapp/data_entry.html', context)


class SearchObjItemAPIView(LoginRequiredMixin, View):
    """
    API endpoint for searching ObjItem by name and coordinates.
    Returns closest matching ObjItem with all required data.
    """
    
    def get(self, request):
        from django.contrib.gis.geos import Point
        from django.contrib.gis.db.models.functions import Distance
        
        name = request.GET.get('name', '').strip()
        satellite_id = request.GET.get('satellite_id', '').strip()
        latitude = request.GET.get('latitude', '').strip()
        longitude = request.GET.get('longitude', '').strip()
        
        if not name:
            return JsonResponse({'error': 'Name parameter is required'}, status=400)
        
        # Build query
        query = Q(name__iexact=name)
        
        # Add satellite filter if provided
        if satellite_id:
            try:
                sat_id = int(satellite_id)
                query &= Q(parameter_obj__id_satellite_id=sat_id)
            except (ValueError, TypeError):
                pass
        
        # Filter ObjItems with geo data
        query &= Q(geo_obj__coords__isnull=False)
        
        # Get queryset
        objitems = ObjItem.objects.filter(query).select_related(
            'parameter_obj',
            'parameter_obj__id_satellite',
            'parameter_obj__polarization',
            'parameter_obj__modulation',
            'parameter_obj__standard',
            'geo_obj'
        ).prefetch_related(
            'geo_obj__mirrors'
        )
        
        # If coordinates provided, find closest point
        if latitude and longitude:
            try:
                lat = float(latitude.replace(',', '.'))
                lon = float(longitude.replace(',', '.'))
                point = Point(lon, lat, srid=4326)
                
                # Order by distance and get closest
                objitem = objitems.annotate(
                    distance=Distance('geo_obj__coords', point)
                ).order_by('distance').first()
            except (ValueError, TypeError):
                # If coordinate parsing fails, just get first match
                objitem = objitems.first()
        else:
            # No coordinates provided, get first match
            objitem = objitems.first()
        
        if not objitem:
            return JsonResponse({'found': False})
        
        # Prepare response data
        data = {
            'found': True,
            'frequency': None,
            'freq_range': None,
            'bod_velocity': None,
            'modulation': None,
            'snr': None,
            'mirrors': None,
        }
        
        # Get parameter data
        if hasattr(objitem, 'parameter_obj') and objitem.parameter_obj:
            param = objitem.parameter_obj
            data['frequency'] = param.frequency if param.frequency else None
            data['freq_range'] = param.freq_range if param.freq_range else None
            data['bod_velocity'] = param.bod_velocity if param.bod_velocity else None
            data['modulation'] = param.modulation.name if param.modulation else None
            data['snr'] = param.snr if param.snr else None
        
        # Get mirrors data
        if hasattr(objitem, 'geo_obj') and objitem.geo_obj:
            mirrors = objitem.geo_obj.mirrors.all()
            if mirrors:
                data['mirrors'] = ', '.join([m.name for m in mirrors])
        
        return JsonResponse(data)
