"""
Представления для управления заявками на источники.
"""
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import JsonResponse
from django.views import View
from django.views.generic import ListView, CreateView, UpdateView
from django.urls import reverse_lazy
from django.db.models import Q

from mainapp.models import SourceRequest, SourceRequestStatusHistory, Source
from mainapp.forms import SourceRequestForm


class SourceRequestListView(LoginRequiredMixin, ListView):
    """Список заявок на источники."""
    model = SourceRequest
    template_name = 'mainapp/source_request_list.html'
    context_object_name = 'requests'
    paginate_by = 50
    
    def get_queryset(self):
        queryset = SourceRequest.objects.select_related(
            'source', 'source__info', 'source__ownership',
            'created_by__user', 'updated_by__user'
        ).order_by('-created_at')
        
        # Фильтр по статусу
        status = self.request.GET.get('status')
        if status:
            queryset = queryset.filter(status=status)
        
        # Фильтр по приоритету
        priority = self.request.GET.get('priority')
        if priority:
            queryset = queryset.filter(priority=priority)
        
        # Фильтр по источнику
        source_id = self.request.GET.get('source_id')
        if source_id:
            queryset = queryset.filter(source_id=source_id)
        
        # Фильтр по ГСО успешно
        gso_success = self.request.GET.get('gso_success')
        if gso_success == 'true':
            queryset = queryset.filter(gso_success=True)
        elif gso_success == 'false':
            queryset = queryset.filter(gso_success=False)
        
        # Фильтр по Кубсат успешно
        kubsat_success = self.request.GET.get('kubsat_success')
        if kubsat_success == 'true':
            queryset = queryset.filter(kubsat_success=True)
        elif kubsat_success == 'false':
            queryset = queryset.filter(kubsat_success=False)
        
        # Поиск
        search = self.request.GET.get('search')
        if search:
            queryset = queryset.filter(
                Q(source__id__icontains=search) |
                Q(comment__icontains=search)
            )
        
        return queryset
    
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['status_choices'] = SourceRequest.STATUS_CHOICES
        context['priority_choices'] = SourceRequest.PRIORITY_CHOICES
        context['current_status'] = self.request.GET.get('status', '')
        context['current_priority'] = self.request.GET.get('priority', '')
        context['search_query'] = self.request.GET.get('search', '')
        context['form'] = SourceRequestForm()
        return context


class SourceRequestCreateView(LoginRequiredMixin, CreateView):
    """Создание заявки на источник."""
    model = SourceRequest
    form_class = SourceRequestForm
    template_name = 'mainapp/source_request_form.html'
    success_url = reverse_lazy('mainapp:source_request_list')
    
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        # Передаем source_id если он есть в GET параметрах
        source_id = self.request.GET.get('source_id')
        if source_id:
            kwargs['source_id'] = source_id
        return kwargs
    
    def form_valid(self, form):
        # Устанавливаем created_by
        form.instance.created_by = getattr(self.request.user, 'customuser', None)
        form.instance.updated_by = getattr(self.request.user, 'customuser', None)
        
        response = super().form_valid(form)
        
        # Создаем начальную запись в истории
        SourceRequestStatusHistory.objects.create(
            source_request=self.object,
            old_status='',
            new_status=self.object.status,
            changed_by=form.instance.created_by,
        )
        
        # Если это AJAX запрос, возвращаем JSON
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': True,
                'message': 'Заявка успешно создана',
                'request_id': self.object.id
            })
        
        return response
    
    def form_invalid(self, form):
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'errors': form.errors
            }, status=400)
        return super().form_invalid(form)


class SourceRequestUpdateView(LoginRequiredMixin, UpdateView):
    """Редактирование заявки на источник."""
    model = SourceRequest
    form_class = SourceRequestForm
    template_name = 'mainapp/source_request_form.html'
    success_url = reverse_lazy('mainapp:source_request_list')
    
    def form_valid(self, form):
        # Устанавливаем updated_by
        form.instance.updated_by = getattr(self.request.user, 'customuser', None)
        
        response = super().form_valid(form)
        
        # Если это AJAX запрос, возвращаем JSON
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': True,
                'message': 'Заявка успешно обновлена',
                'request_id': self.object.id
            })
        
        return response
    
    def form_invalid(self, form):
        if self.request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return JsonResponse({
                'success': False,
                'errors': form.errors
            }, status=400)
        return super().form_invalid(form)


class SourceRequestDeleteView(LoginRequiredMixin, View):
    """Удаление заявки на источник."""
    
    def post(self, request, pk):
        try:
            source_request = SourceRequest.objects.get(pk=pk)
            source_request.delete()
            return JsonResponse({
                'success': True,
                'message': 'Заявка успешно удалена'
            })
        except SourceRequest.DoesNotExist:
            return JsonResponse({
                'success': False,
                'error': 'Заявка не найдена'
            }, status=404)


class SourceRequestAPIView(LoginRequiredMixin, View):
    """API для получения данных о заявках источника."""
    
    def get(self, request, source_id):
        try:
            source = Source.objects.get(pk=source_id)
        except Source.DoesNotExist:
            return JsonResponse({'error': 'Источник не найден'}, status=404)
        
        requests = SourceRequest.objects.filter(source=source).select_related(
            'created_by__user', 'updated_by__user'
        ).prefetch_related('status_history__changed_by__user').order_by('-created_at')
        
        data = []
        for req in requests:
            # Получаем историю статусов
            history = []
            for h in req.status_history.all().order_by('-changed_at'):
                history.append({
                    'old_status': h.get_old_status_display() if h.old_status else '-',
                    'new_status': h.get_new_status_display(),
                    'changed_at': h.changed_at.strftime('%d.%m.%Y %H:%M') if h.changed_at else '-',
                    'changed_by': str(h.changed_by) if h.changed_by else '-',
                })
            
            data.append({
                'id': req.id,
                'status': req.status,
                'status_display': req.get_status_display(),
                'priority': req.priority,
                'priority_display': req.get_priority_display(),
                'planned_at': req.planned_at.strftime('%d.%m.%Y %H:%M') if req.planned_at else '-',
                'request_date': req.request_date.strftime('%d.%m.%Y') if req.request_date else '-',
                'status_updated_at': req.status_updated_at.strftime('%d.%m.%Y %H:%M') if req.status_updated_at else '-',
                'gso_success': req.gso_success,
                'kubsat_success': req.kubsat_success,
                'comment': req.comment or '-',
                'created_at': req.created_at.strftime('%d.%m.%Y %H:%M') if req.created_at else '-',
                'created_by': str(req.created_by) if req.created_by else '-',
                'history': history,
            })
        
        return JsonResponse({
            'source_id': source_id,
            'requests': data,
            'count': len(data)
        })


class SourceRequestDetailAPIView(LoginRequiredMixin, View):
    """API для получения детальной информации о заявке."""
    
    def get(self, request, pk):
        try:
            req = SourceRequest.objects.select_related(
                'source', 'source__info', 'source__ownership',
                'created_by__user', 'updated_by__user'
            ).prefetch_related(
                'status_history__changed_by__user',
                'source__source_objitems__parameter_obj__modulation',
                'source__source_objitems__geo_obj'
            ).get(pk=pk)
        except SourceRequest.DoesNotExist:
            return JsonResponse({'error': 'Заявка не найдена'}, status=404)
        
        # Получаем историю статусов
        history = []
        for h in req.status_history.all().order_by('-changed_at'):
            history.append({
                'old_status': h.get_old_status_display() if h.old_status else '-',
                'new_status': h.get_new_status_display(),
                'changed_at': h.changed_at.strftime('%d.%m.%Y %H:%M') if h.changed_at else '-',
                'changed_by': str(h.changed_by) if h.changed_by else '-',
            })
        
        # Получаем данные из первой точки источника (имя, модуляция, символьная скорость)
        source_data = _get_source_extra_data(req.source)
        
        # Координаты из заявки или из источника
        coords_lat = None
        coords_lon = None
        if req.coords:
            coords_lat = req.coords.y
            coords_lon = req.coords.x
        elif req.source.coords_average:
            coords_lat = req.source.coords_average.y
            coords_lon = req.source.coords_average.x
        
        data = {
            'id': req.id,
            'source_id': req.source_id,
            'status': req.status,
            'status_display': req.get_status_display(),
            'priority': req.priority,
            'priority_display': req.get_priority_display(),
            'planned_at': req.planned_at.isoformat() if req.planned_at else None,
            'planned_at_display': req.planned_at.strftime('%d.%m.%Y %H:%M') if req.planned_at else '-',
            'request_date': req.request_date.isoformat() if req.request_date else None,
            'request_date_display': req.request_date.strftime('%d.%m.%Y') if req.request_date else '-',
            'status_updated_at': req.status_updated_at.strftime('%d.%m.%Y %H:%M') if req.status_updated_at else '-',
            'gso_success': req.gso_success,
            'kubsat_success': req.kubsat_success,
            'comment': req.comment or '',
            'created_at': req.created_at.strftime('%d.%m.%Y %H:%M') if req.created_at else '-',
            'created_by': str(req.created_by) if req.created_by else '-',
            'history': history,
            # Дополнительные данные
            'coords_lat': coords_lat,
            'coords_lon': coords_lon,
            'points_count': req.points_count,
            'objitem_name': source_data['objitem_name'],
            'modulation': source_data['modulation'],
            'symbol_rate': source_data['symbol_rate'],
        }
        
        return JsonResponse(data)


def _get_source_extra_data(source):
    """Получает дополнительные данные из первой точки источника."""
    objitem_name = '-'
    modulation = '-'
    symbol_rate = '-'
    
    if source:
        # Получаем первую точку источника (сортируем по дате ГЛ)
        objitems = source.source_objitems.select_related(
            'parameter_obj__modulation', 'geo_obj'
        ).order_by('geo_obj__timestamp')
        
        first_objitem = objitems.first()
        if first_objitem:
            objitem_name = first_objitem.name or '-'
            if first_objitem.parameter_obj:
                if first_objitem.parameter_obj.modulation:
                    modulation = first_objitem.parameter_obj.modulation.name
                if first_objitem.parameter_obj.bod_velocity and first_objitem.parameter_obj.bod_velocity > 0:
                    symbol_rate = str(int(first_objitem.parameter_obj.bod_velocity))
    
    return {
        'objitem_name': objitem_name,
        'modulation': modulation,
        'symbol_rate': symbol_rate,
    }


class SourceDataAPIView(LoginRequiredMixin, View):
    """API для получения данных источника (координаты, имя точки, модуляция, символьная скорость)."""
    
    def get(self, request, source_id):
        from mainapp.utils import calculate_mean_coords
        from datetime import datetime
        
        try:
            source = Source.objects.select_related('info', 'ownership').prefetch_related(
                'source_objitems__parameter_obj__modulation',
                'source_objitems__geo_obj'
            ).get(pk=source_id)
        except Source.DoesNotExist:
            return JsonResponse({'error': 'Источник не найден', 'found': False}, status=404)
        
        # Получаем данные из точек источника
        source_data = _get_source_extra_data(source)
        
        # Рассчитываем усреднённые координаты из всех точек (сортируем по дате ГЛ)
        objitems = source.source_objitems.select_related('geo_obj').order_by('geo_obj__timestamp')
        
        avg_coords = None
        points_count = 0
        for objitem in objitems:
            if hasattr(objitem, 'geo_obj') and objitem.geo_obj and objitem.geo_obj.coords:
                coord = (float(objitem.geo_obj.coords.x), float(objitem.geo_obj.coords.y))
                points_count += 1
                if avg_coords is None:
                    avg_coords = coord
                else:
                    avg_coords, _ = calculate_mean_coords(avg_coords, coord)
        
        # Если нет координат из точек, берём из источника
        coords_lat = None
        coords_lon = None
        if avg_coords:
            coords_lon = avg_coords[0]
            coords_lat = avg_coords[1]
        elif source.coords_average:
            coords_lat = source.coords_average.y
            coords_lon = source.coords_average.x
        
        data = {
            'found': True,
            'source_id': source_id,
            'coords_lat': coords_lat,
            'coords_lon': coords_lon,
            'points_count': points_count,
            'objitem_name': source_data['objitem_name'],
            'modulation': source_data['modulation'],
            'symbol_rate': source_data['symbol_rate'],
            'info': source.info.name if source.info else '-',
            'ownership': source.ownership.name if source.ownership else '-',
        }
        
        return JsonResponse(data)
