from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import Paginator
from django.db.models import Q
from django.views.generic import ListView

from .models import LyngSat
from mainapp.models import Satellite, Polarization, Modulation, Standard
from mainapp.utils import parse_pagination_params


class LyngSatListView(LoginRequiredMixin, ListView):
    """
    Представление для отображения списка источников LyngSat с фильтрацией и пагинацией.
    """
    model = LyngSat
    template_name = 'lyngsatapp/lyngsat_list.html'
    context_object_name = 'lyngsat_items'
    paginate_by = 50

    def get_queryset(self):
        """
        Возвращает отфильтрованный и отсортированный queryset.
        """
        queryset = LyngSat.objects.select_related(
            'id_satellite',
            'polarization',
            'modulation',
            'standard'
        ).all()

        # Поиск по ID
        search_query = self.request.GET.get('search', '').strip()
        if search_query:
            try:
                search_id = int(search_query)
                queryset = queryset.filter(id=search_id)
            except ValueError:
                queryset = queryset.none()

        # Фильтр по спутнику
        satellite_ids = self.request.GET.getlist('satellite_id')
        if satellite_ids:
            queryset = queryset.filter(id_satellite_id__in=satellite_ids)

        # Фильтр по поляризации
        polarization_ids = self.request.GET.getlist('polarization_id')
        if polarization_ids:
            queryset = queryset.filter(polarization_id__in=polarization_ids)

        # Фильтр по модуляции
        modulation_ids = self.request.GET.getlist('modulation_id')
        if modulation_ids:
            queryset = queryset.filter(modulation_id__in=modulation_ids)

        # Фильтр по стандарту
        standard_ids = self.request.GET.getlist('standard_id')
        if standard_ids:
            queryset = queryset.filter(standard_id__in=standard_ids)

        # Фильтр по частоте
        freq_min = self.request.GET.get('freq_min', '').strip()
        freq_max = self.request.GET.get('freq_max', '').strip()
        if freq_min:
            try:
                queryset = queryset.filter(frequency__gte=float(freq_min))
            except ValueError:
                pass
        if freq_max:
            try:
                queryset = queryset.filter(frequency__lte=float(freq_max))
            except ValueError:
                pass

        # Фильтр по символьной скорости
        sym_min = self.request.GET.get('sym_min', '').strip()
        sym_max = self.request.GET.get('sym_max', '').strip()
        if sym_min:
            try:
                queryset = queryset.filter(sym_velocity__gte=float(sym_min))
            except ValueError:
                pass
        if sym_max:
            try:
                queryset = queryset.filter(sym_velocity__lte=float(sym_max))
            except ValueError:
                pass

        # Фильтр по дате обновления
        date_from = self.request.GET.get('date_from', '').strip()
        date_to = self.request.GET.get('date_to', '').strip()
        if date_from:
            queryset = queryset.filter(last_update__gte=date_from)
        if date_to:
            queryset = queryset.filter(last_update__lte=date_to)

        # Сортировка
        sort = self.request.GET.get('sort', '-id')
        valid_sort_fields = ['id', '-id', 'frequency', '-frequency', 'sym_velocity', '-sym_velocity', 'last_update', '-last_update']
        if sort in valid_sort_fields:
            queryset = queryset.order_by(sort)
        else:
            queryset = queryset.order_by('-id')

        return queryset

    def get_context_data(self, **kwargs):
        """
        Добавляет дополнительный контекст для шаблона.
        """
        context = super().get_context_data(**kwargs)

        # Параметры пагинации
        page_number, items_per_page = parse_pagination_params(self.request, default_per_page=50)
        context['items_per_page'] = items_per_page
        context['available_items_per_page'] = [25, 50, 100, 200, 500]

        # Пагинация
        paginator = Paginator(self.get_queryset(), items_per_page)
        page_obj = paginator.get_page(page_number)
        context['page_obj'] = page_obj
        context['lyngsat_items'] = page_obj.object_list

        # Параметры поиска и фильтрации
        context['search_query'] = self.request.GET.get('search', '')
        context['sort'] = self.request.GET.get('sort', '-id')

        # Данные для фильтров - только спутники с существующими записями LyngSat
        satellites = Satellite.objects.filter(
            lyngsat__isnull=False
        ).distinct().order_by('name')
        polarizations = Polarization.objects.all().order_by('name')
        modulations = Modulation.objects.all().order_by('name')
        standards = Standard.objects.all().order_by('name')

        # Выбранные фильтры
        selected_satellites = [int(x) for x in self.request.GET.getlist('satellite_id') if x.isdigit()]
        selected_polarizations = [int(x) for x in self.request.GET.getlist('polarization_id') if x.isdigit()]
        selected_modulations = [int(x) for x in self.request.GET.getlist('modulation_id') if x.isdigit()]
        selected_standards = [int(x) for x in self.request.GET.getlist('standard_id') if x.isdigit()]

        # Параметры фильтров
        freq_min = self.request.GET.get('freq_min', '')
        freq_max = self.request.GET.get('freq_max', '')
        sym_min = self.request.GET.get('sym_min', '')
        sym_max = self.request.GET.get('sym_max', '')
        date_from = self.request.GET.get('date_from', '')
        date_to = self.request.GET.get('date_to', '')

        # Action buttons HTML for toolbar component
        from django.urls import reverse
        action_buttons_html = f'''
            <a href="{reverse('mainapp:fill_lyngsat_data')}" class="btn btn-secondary btn-sm" title="Заполнить данные Lyngsat">
                <i class="bi bi-cloud-download"></i> Добавить данные
            </a>
            <a href="{reverse('mainapp:link_lyngsat')}" class="btn btn-primary btn-sm" title="Привязать источники LyngSat">
                <i class="bi bi-link-45deg"></i> Привязать
            </a>
            <a href="{reverse('mainapp:unlink_all_lyngsat')}" class="btn btn-warning btn-sm" title="Отвязать все источники LyngSat">
                <i class="bi bi-x-circle"></i> Отвязать
            </a>
        '''
        context['action_buttons_html'] = action_buttons_html

        # Build filter HTML list for filter_panel component
        filter_html_list = []

        # Satellite filter
        satellite_options = ''.join([
            f'<option value="{sat.id}" {"selected" if sat.id in selected_satellites else ""}>{sat.name}</option>'
            for sat in satellites
        ])
        filter_html_list.append(f'''
            <div class="mb-2">
                <label class="form-label">Спутник:</label>
                <div class="d-flex justify-content-between mb-1">
                    <button type="button" class="btn btn-sm btn-outline-secondary"
                        onclick="selectAllOptions('satellite_id', true)">Выбрать</button>
                    <button type="button" class="btn btn-sm btn-outline-secondary"
                        onclick="selectAllOptions('satellite_id', false)">Снять</button>
                </div>
                <select name="satellite_id" class="form-select form-select-sm mb-2" multiple size="6">
                    {satellite_options}
                </select>
            </div>
        ''')

        # Polarization filter
        polarization_options = ''.join([
            f'<option value="{pol.id}" {"selected" if pol.id in selected_polarizations else ""}>{pol.name}</option>'
            for pol in polarizations
        ])
        filter_html_list.append(f'''
            <div class="mb-2">
                <label class="form-label">Поляризация:</label>
                <div class="d-flex justify-content-between mb-1">
                    <button type="button" class="btn btn-sm btn-outline-secondary"
                        onclick="selectAllOptions('polarization_id', true)">Выбрать</button>
                    <button type="button" class="btn btn-sm btn-outline-secondary"
                        onclick="selectAllOptions('polarization_id', false)">Снять</button>
                </div>
                <select name="polarization_id" class="form-select form-select-sm mb-2" multiple size="4">
                    {polarization_options}
                </select>
            </div>
        ''')

        # Modulation filter
        modulation_options = ''.join([
            f'<option value="{mod.id}" {"selected" if mod.id in selected_modulations else ""}>{mod.name}</option>'
            for mod in modulations
        ])
        filter_html_list.append(f'''
            <div class="mb-2">
                <label class="form-label">Модуляция:</label>
                <div class="d-flex justify-content-between mb-1">
                    <button type="button" class="btn btn-sm btn-outline-secondary"
                        onclick="selectAllOptions('modulation_id', true)">Выбрать</button>
                    <button type="button" class="btn btn-sm btn-outline-secondary"
                        onclick="selectAllOptions('modulation_id', false)">Снять</button>
                </div>
                <select name="modulation_id" class="form-select form-select-sm mb-2" multiple size="4">
                    {modulation_options}
                </select>
            </div>
        ''')

        # Standard filter
        standard_options = ''.join([
            f'<option value="{std.id}" {"selected" if std.id in selected_standards else ""}>{std.name}</option>'
            for std in standards
        ])
        filter_html_list.append(f'''
            <div class="mb-2">
                <label class="form-label">Стандарт:</label>
                <div class="d-flex justify-content-between mb-1">
                    <button type="button" class="btn btn-sm btn-outline-secondary"
                        onclick="selectAllOptions('standard_id', true)">Выбрать</button>
                    <button type="button" class="btn btn-sm btn-outline-secondary"
                        onclick="selectAllOptions('standard_id', false)">Снять</button>
                </div>
                <select name="standard_id" class="form-select form-select-sm mb-2" multiple size="4">
                    {standard_options}
                </select>
            </div>
        ''')

        # Frequency filter
        filter_html_list.append(f'''
            <div class="mb-2">
                <label class="form-label">Частота, МГц:</label>
                <input type="number" step="0.001" name="freq_min" class="form-control form-control-sm mb-1"
                    placeholder="От" value="{freq_min}">
                <input type="number" step="0.001" name="freq_max" class="form-control form-control-sm"
                    placeholder="До" value="{freq_max}">
            </div>
        ''')

        # Symbol rate filter
        filter_html_list.append(f'''
            <div class="mb-2">
                <label class="form-label">Символьная скорость, БОД:</label>
                <input type="number" step="0.001" name="sym_min" class="form-control form-control-sm mb-1"
                    placeholder="От" value="{sym_min}">
                <input type="number" step="0.001" name="sym_max" class="form-control form-control-sm"
                    placeholder="До" value="{sym_max}">
            </div>
        ''')

        # Date filter
        filter_html_list.append(f'''
            <div class="mb-2">
                <label class="form-label">Дата обновления:</label>
                <input type="date" name="date_from" id="date_from" class="form-control form-control-sm mb-1"
                    placeholder="От" value="{date_from}">
                <input type="date" name="date_to" id="date_to" class="form-control form-control-sm"
                    placeholder="До" value="{date_to}">
            </div>
        ''')

        context['filter_html_list'] = filter_html_list
        
        # Enable full width layout
        context['full_width_page'] = True

        return context
