"""
Transponder CRUD operations and related views.
"""
from datetime import datetime

from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import Paginator
from django.db.models import Count, Q
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse, reverse_lazy
from django.views import View
from django.views.generic import CreateView, UpdateView

from mapsapp.models import Transponders
from ..forms import TransponderForm
from ..mixins import FormMessageMixin
from ..permissions import PermissionRequiredMixin
from ..models import Satellite, Polarization
from ..utils import parse_pagination_params


class TransponderListView(LoginRequiredMixin, View):
    """View for displaying a list of transponders with filtering and pagination."""
    
    def get(self, request):
        # Get pagination parameters
        page_number, items_per_page = parse_pagination_params(request)
        
        # Get sorting parameters (default to satellite and downlink)
        sort_param = request.GET.get("sort", "sat_id__name")
        
        # Get filter parameters
        search_query = request.GET.get("search", "").strip()
        selected_satellites = request.GET.getlist("satellite_id")
        selected_polarizations = request.GET.getlist("polarization")
        downlink_min = request.GET.get("downlink_min", "").strip()
        downlink_max = request.GET.get("downlink_max", "").strip()
        uplink_min = request.GET.get("uplink_min", "").strip()
        uplink_max = request.GET.get("uplink_max", "").strip()
        freq_range_min = request.GET.get("freq_range_min", "").strip()
        freq_range_max = request.GET.get("freq_range_max", "").strip()
        snr_min = request.GET.get("snr_min", "").strip()
        snr_max = request.GET.get("snr_max", "").strip()
        date_from = request.GET.get("date_from", "").strip()
        date_to = request.GET.get("date_to", "").strip()
        
        # Get all satellites and polarizations for filters
        satellites = Satellite.objects.filter(
            tran_satellite__isnull=False
        ).distinct().only("id", "name").order_by("name")
        
        polarizations = Polarization.objects.all().order_by("name")
        
        # Get all transponders with query optimization
        transponders = Transponders.objects.select_related(
            'sat_id',
            'polarization',
            'created_by__user',
            'updated_by__user'
        ).annotate(
            objitem_count=Count('transponder_objitems')
        )
        
        # Apply filters
        # Filter by satellites
        if selected_satellites:
            transponders = transponders.filter(sat_id_id__in=selected_satellites)
        
        # Filter by polarizations
        if selected_polarizations:
            transponders = transponders.filter(polarization_id__in=selected_polarizations)
        
        # Filter by downlink frequency
        if downlink_min:
            try:
                min_val = float(downlink_min)
                transponders = transponders.filter(downlink__gte=min_val)
            except ValueError:
                pass
        
        if downlink_max:
            try:
                max_val = float(downlink_max)
                transponders = transponders.filter(downlink__lte=max_val)
            except ValueError:
                pass
        
        # Filter by uplink frequency
        if uplink_min:
            try:
                min_val = float(uplink_min)
                transponders = transponders.filter(uplink__gte=min_val)
            except ValueError:
                pass
        
        if uplink_max:
            try:
                max_val = float(uplink_max)
                transponders = transponders.filter(uplink__lte=max_val)
            except ValueError:
                pass
        
        # Filter by frequency range
        if freq_range_min:
            try:
                min_val = float(freq_range_min)
                transponders = transponders.filter(frequency_range__gte=min_val)
            except ValueError:
                pass
        
        if freq_range_max:
            try:
                max_val = float(freq_range_max)
                transponders = transponders.filter(frequency_range__lte=max_val)
            except ValueError:
                pass
        
        # Filter by SNR
        if snr_min:
            try:
                min_val = float(snr_min)
                transponders = transponders.filter(snr__gte=min_val)
            except ValueError:
                pass
        
        if snr_max:
            try:
                max_val = float(snr_max)
                transponders = transponders.filter(snr__lte=max_val)
            except ValueError:
                pass
        
        # Filter by creation date range
        if date_from:
            try:
                date_from_obj = datetime.strptime(date_from, "%Y-%m-%d")
                transponders = transponders.filter(created_at__gte=date_from_obj)
            except (ValueError, TypeError):
                pass
        
        if date_to:
            try:
                from datetime import timedelta
                date_to_obj = datetime.strptime(date_to, "%Y-%m-%d")
                # Add one day to include entire end date
                date_to_obj = date_to_obj + timedelta(days=1)
                transponders = transponders.filter(created_at__lt=date_to_obj)
            except (ValueError, TypeError):
                pass
        
        # Search by name or zone name
        if search_query:
            transponders = transponders.filter(
                Q(name__icontains=search_query) |
                Q(zone_name__icontains=search_query) |
                Q(sat_id__name__icontains=search_query)
            )
        
        # Apply sorting
        valid_sort_fields = {
            "sat_id__name": "sat_id__name",
            "-sat_id__name": "-sat_id__name",
            "name": "name",
            "-name": "-name",
            "downlink": "downlink",
            "-downlink": "-downlink",
            "uplink": "uplink",
            "-uplink": "-uplink",
            "frequency_range": "frequency_range",
            "-frequency_range": "-frequency_range",
            "zone_name": "zone_name",
            "-zone_name": "-zone_name",
            "polarization__name": "polarization__name",
            "-polarization__name": "-polarization__name",
            "snr": "snr",
            "-snr": "-snr",
            "created_at": "created_at",
            "-created_at": "-created_at",
            "updated_at": "updated_at",
            "-updated_at": "-updated_at",
            "objitem_count": "objitem_count",
            "-objitem_count": "-objitem_count",
        }
        
        if sort_param in valid_sort_fields:
            transponders = transponders.order_by(valid_sort_fields[sort_param])
        
        # Create paginator
        paginator = Paginator(transponders, items_per_page)
        page_obj = paginator.get_page(page_number)
        
        # Prepare data for display
        processed_transponders = []
        for transponder in page_obj:
            processed_transponders.append({
                'id': transponder.id,
                'name': transponder.name or "-",
                'satellite': transponder.sat_id.name if transponder.sat_id else "-",
                'satellite_id': transponder.sat_id.id if transponder.sat_id else None,
                'downlink': f"{transponder.downlink:.3f}" if transponder.downlink else "-",
                'uplink': f"{transponder.uplink:.3f}" if transponder.uplink else "-",
                'frequency_range': f"{transponder.frequency_range:.3f}" if transponder.frequency_range else "-",
                'transfer': f"{transponder.transfer:.3f}" if transponder.transfer else "-",
                'zone_name': transponder.zone_name or "-",
                'polarization': transponder.polarization.name if transponder.polarization else "-",
                'snr': f"{transponder.snr:.1f}" if transponder.snr else "-",
                'objitem_count': transponder.objitem_count,
                'created_at': transponder.created_at,
                'updated_at': transponder.updated_at,
                'created_by': transponder.created_by if transponder.created_by else "-",
                'updated_by': transponder.updated_by if transponder.updated_by else "-",
            })
        
        # Prepare context for template
        context = {
            'page_obj': page_obj,
            'processed_transponders': processed_transponders,
            'items_per_page': items_per_page,
            'available_items_per_page': [50, 100, 500, 1000],
            'sort': sort_param,
            'search_query': search_query,
            'satellites': satellites,
            'polarizations': polarizations,
            'selected_satellites': [
                int(x) if isinstance(x, str) else x for x in selected_satellites 
                if (isinstance(x, int) or (isinstance(x, str) and x.isdigit()))
            ],
            'selected_polarizations': [
                int(x) if isinstance(x, str) else x for x in selected_polarizations 
                if (isinstance(x, int) or (isinstance(x, str) and x.isdigit()))
            ],
            'downlink_min': downlink_min,
            'downlink_max': downlink_max,
            'uplink_min': uplink_min,
            'uplink_max': uplink_max,
            'freq_range_min': freq_range_min,
            'freq_range_max': freq_range_max,
            'snr_min': snr_min,
            'snr_max': snr_max,
            'date_from': date_from,
            'date_to': date_to,
            'full_width_page': True,
        }
        
        return render(request, "mainapp/transponder_list.html", context)


class TransponderCreateView(PermissionRequiredMixin, FormMessageMixin, CreateView):
    """View for creating a new transponder."""
    
    permission_required = 'transponder_create'
    model = Transponders
    form_class = TransponderForm
    template_name = "mainapp/transponder_form.html"
    success_url = reverse_lazy("mainapp:transponder_list")
    success_message = "Транспондер успешно создан!"
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['action'] = 'create'
        context['title'] = 'Создание транспондера'
        return context
    
    def form_valid(self, form):
        form.instance.created_by = self.request.user.customuser
        form.instance.updated_by = self.request.user.customuser
        return super().form_valid(form)


class TransponderUpdateView(PermissionRequiredMixin, FormMessageMixin, UpdateView):
    """View for updating an existing transponder."""
    
    permission_required = 'transponder_edit'
    model = Transponders
    form_class = TransponderForm
    template_name = "mainapp/transponder_form.html"
    success_url = reverse_lazy("mainapp:transponder_list")
    success_message = "Транспондер успешно обновлен!"
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['action'] = 'update'
        context['title'] = f'Редактирование транспондера #{self.object.id}'
        
        # Get related objitems count
        context['objitem_count'] = self.object.transponder_objitems.count()
        
        return context
    
    def form_valid(self, form):
        form.instance.updated_by = self.request.user.customuser
        return super().form_valid(form)


class DeleteSelectedTranspondersView(PermissionRequiredMixin, View):
    """View for deleting multiple selected transponders with confirmation."""
    
    permission_required = 'transponder_delete'
    
    def get(self, request):
        """Show confirmation page with details about transponders to be deleted."""
        ids = request.GET.get("ids", "")
        if not ids:
            messages.error(request, "Не выбраны транспондеры для удаления")
            return redirect('mainapp:transponder_list')
        
        try:
            id_list = [int(x) for x in ids.split(",") if x.isdigit()]
            transponders = Transponders.objects.filter(id__in=id_list).select_related(
                'sat_id',
                'polarization'
            ).annotate(
                objitem_count=Count('transponder_objitems')
            )
            
            # Prepare detailed information about transponders
            transponders_info = []
            total_objitems = 0
            
            for transponder in transponders:
                objitem_count = transponder.objitem_count
                total_objitems += objitem_count
                
                transponders_info.append({
                    'id': transponder.id,
                    'name': transponder.name or "-",
                    'satellite': transponder.sat_id.name if transponder.sat_id else "-",
                    'downlink': f"{transponder.downlink:.3f}" if transponder.downlink else "-",
                    'frequency_range': f"{transponder.frequency_range:.3f}" if transponder.frequency_range else "-",
                    'objitem_count': objitem_count,
                })
            
            context = {
                'transponders_info': transponders_info,
                'total_transponders': len(transponders_info),
                'total_objitems': total_objitems,
                'ids': ids,
            }
            
            return render(request, 'mainapp/transponder_bulk_delete_confirm.html', context)
            
        except Exception as e:
            messages.error(request, f'Ошибка при подготовке удаления: {str(e)}')
            return redirect('mainapp:transponder_list')
    
    def post(self, request):
        """Actually delete the selected transponders."""
        ids = request.POST.get("ids", "")
        if not ids:
            return JsonResponse({"error": "Нет ID для удаления"}, status=400)
        
        try:
            id_list = [int(x) for x in ids.split(",") if x.isdigit()]
            
            # Get count before deletion
            transponders = Transponders.objects.filter(id__in=id_list)
            deleted_count = transponders.count()
            
            # Delete transponders (cascade will handle related objitems)
            transponders.delete()
            
            messages.success(
                request, 
                f'Успешно удалено транспондеров: {deleted_count}'
            )
            
            return JsonResponse({
                "success": True,
                "message": f"Успешно удалено транспондеров: {deleted_count}",
                "deleted_count": deleted_count,
            })
            
        except Exception as e:
            return JsonResponse({"error": f"Ошибка при удалении: {str(e)}"}, status=500)
