"""
Представление для каталога товаров и комплектов.
"""
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView
from django.db.models import Prefetch, Sum, Value, DecimalField, Q
from django.db.models.functions import Coalesce
from django.core.paginator import Paginator
from django.urls import reverse_lazy

from ..models import Product, ProductKit, ProductCategory, ProductPhoto, ProductKitPhoto, KitItem


class CatalogView(LoginRequiredMixin, ListView):
    """Каталог с деревом категорий слева и сеткой товаров справа с пагинацией."""
    template_name = 'products/catalog.html'
    context_object_name = 'items'
    paginate_by = 50

    def build_category_tree(self, categories, parent=None):
        """Рекурсивно строит дерево категорий с товарами."""
        tree = []
        for cat in categories:
            if cat.parent_id == (parent.pk if parent else None):
                children = self.build_category_tree(categories, cat)
                tree.append({
                    'category': cat,
                    'children': children,
                })
        return tree

    def get_queryset(self):
        """Получаем объединенный список товаров и комплектов с оптимизацией."""
        # Аннотации для остатков
        total_available = Coalesce(Sum('stocks__quantity_available'), Value(0), output_field=DecimalField())
        total_reserved = Coalesce(Sum('stocks__quantity_reserved'), Value(0), output_field=DecimalField())

        # Prefetch главного фото для товаров
        # Берем первое фото по ordering (is_main=True будет первым, если есть)
        # Это работает даже если is_main не установлен
        main_product_photo = Prefetch(
            'photos',
            queryset=ProductPhoto.objects.all()[:1],
            to_attr='main_photo_list'
        )

        # Товары с фотографиями и остатками
        products = Product.objects.filter(status='active').prefetch_related(
            main_product_photo,
            'categories'
        ).annotate(
            total_available=total_available,
            total_reserved=total_reserved,
        ).order_by('name')

        # Prefetch главного фото для комплектов
        # Берем первое фото по ordering (is_main=True будет первым, если есть)
        main_kit_photo = Prefetch(
            'photos',
            queryset=ProductKitPhoto.objects.all()[:1],
            to_attr='main_photo_list'
        )

        # Комплекты с фотографиями
        kits = ProductKit.objects.filter(status='active', is_temporary=False).prefetch_related(
            main_kit_photo,
            'categories',
            Prefetch(
                'kit_items',
                queryset=KitItem.objects.select_related(
                    'product', 'variant_group'
                ).prefetch_related('product__stocks')
            )
        ).order_by('name')

        # Объединяем товары и комплекты
        items_list = []
        
        for p in products:
            p.item_type = 'product'
            # Используем кешированное главное фото из prefetch
            p.cached_main_photo = p.main_photo_list[0] if p.main_photo_list else None
            # Кешируем категории для избежания повторных запросов
            p.cached_categories = list(p.categories.all())
            p.total_free = p.total_available - p.total_reserved
            items_list.append(p)
        
        for k in kits:
            k.item_type = 'kit'
            # Используем кешированное главное фото из prefetch
            k.cached_main_photo = k.main_photo_list[0] if k.main_photo_list else None
            # Кешируем категории для избежания повторных запросов
            k.cached_categories = list(k.categories.all())
            # Кешируем результат calculate_available_quantity
            k.total_free = k.calculate_available_quantity()
            items_list.append(k)

        # Сортируем по имени
        items_list.sort(key=lambda x: x.name)
        
        return items_list

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Все активные категории для дерева
        categories = list(ProductCategory.objects.filter(
            is_active=True, is_deleted=False
        ).order_by('name'))

        # Строим дерево
        category_tree = self.build_category_tree(categories, parent=None)
        context['category_tree'] = category_tree
        
        # Кнопки действий
        action_buttons = []

        if self.request.user.has_perm('products.add_product'):
            action_buttons.append({
                'url': reverse_lazy('products:product-create'),
                'text': 'Создать товар',
                'class': 'btn-primary',
                'icon': 'plus-circle'
            })

        if self.request.user.has_perm('products.add_productkit'):
            action_buttons.append({
                'url': reverse_lazy('products:productkit-create'),
                'text': 'Создать комплект',
                'class': 'btn-outline-primary',
                'icon': 'box-seam'
            })

        if self.request.user.has_perm('products.add_configurableproduct'):
            action_buttons.append({
                'url': reverse_lazy('products:configurableproduct-create'),
                'text': 'Создать вариативный товар',
                'class': 'btn-outline-success',
                'icon': 'grid-3x3-gap'
            })

        if self.request.user.has_perm('products.add_productvariantgroup'):
            action_buttons.append({
                'url': reverse_lazy('products:variantgroup-create'),
                'text': 'Создать группу вариантов',
                'class': 'btn-outline-info',
                'icon': 'collection'
            })

        context['action_buttons'] = action_buttons
        
        return context
