"""
Админка для приложения products.
Все модели tenant-only, поэтому используют TenantAdminOnlyMixin
для скрытия от public admin (localhost/admin/).
"""
from django.contrib import admin
from django.utils.html import format_html
from django.utils import timezone
from django.db.models import Q
import nested_admin
from .models import ProductCategory, ProductTag, Product, ProductKit, KitItem
from .models import ProductPhoto, ProductKitPhoto, ProductCategoryPhoto
from .models import ProductVariantGroup, KitItemPriority, SKUCounter, CostPriceHistory
from .models import ConfigurableProduct, ConfigurableProductOption, ConfigurableProductAttribute
from .models import UnitOfMeasure, ProductSalesUnit
from .models import BouquetName
from .admin_displays import (
    format_quality_badge,
    format_quality_display,
    format_photo_quality_column,
    format_photo_inline_quality,
    format_photo_preview_with_quality,
)
from tenants.admin_mixins import TenantAdminOnlyMixin


class DeletedFilter(admin.SimpleListFilter):
    """Фильтр для отображения удаленных/активных элементов"""
    title = 'Статус'
    parameter_name = 'status'

    def lookups(self, request, model_admin):
        return (
            ('active', 'Активные'),
            ('archived', 'Архивные'),
            ('discontinued', 'Снятые'),
        )

    def queryset(self, request, queryset):
        # queryset уже содержит всё благодаря get_queryset()
        # Проверяем есть ли поле status или is_deleted на модели
        if hasattr(queryset.model, 'status'):
            if self.value() == 'active':
                return queryset.filter(status='active')
            elif self.value() == 'archived':
                return queryset.filter(status='archived')
            elif self.value() == 'discontinued':
                return queryset.filter(status='discontinued')
        elif hasattr(queryset.model, 'is_deleted'):
            # Для старой системы (Category, Tag)
            if self.value() == '0':
                return queryset.filter(is_deleted=False)
            elif self.value() == '1':
                return queryset.filter(is_deleted=True)
        return queryset


class QualityLevelFilter(admin.SimpleListFilter):
    """Фильтр для отображения товаров по качеству их фотографий"""
    title = 'Качество фото'
    parameter_name = 'photo_quality'

    def lookups(self, request, model_admin):
        return (
            ('excellent', '🟢 Отлично'),
            ('good', '🟡 Хорошо'),
            ('acceptable', '🟠 Приемлемо'),
            ('poor', '🔴 Плохо'),
            ('very_poor', '🔴🔴 Очень плохо'),
            ('warning', '⚠️ Требует обновления'),
            ('no_warning', '✓ Готово к выгрузке'),
        )

    def queryset(self, request, queryset):
        if self.value() == 'warning':
            # Товары, у которых есть фото с quality_warning=True
            return queryset.filter(photos__quality_warning=True).distinct()
        elif self.value() == 'no_warning':
            # Товары, у которых есть фото БЕЗ warning (excellent или good)
            return queryset.filter(
                photos__quality_level__in=['excellent', 'good']
            ).distinct()
        elif self.value():
            # По конкретному уровню качества
            return queryset.filter(photos__quality_level=self.value()).distinct()
        return queryset


def restore_items(modeladmin, request, queryset):
    """Action для восстановления удаленных элементов"""
    if hasattr(queryset.model, 'status'):
        # Новая система со статусом
        updated = queryset.update(status='active', archived_at=None, archived_by=None)
    else:
        # Старая система с is_deleted
        updated = queryset.update(is_deleted=False, deleted_at=None, deleted_by=None)
    modeladmin.message_user(request, f'✓ Восстановлено {updated} элемент(ов).')
restore_items.short_description = '✓ Восстановить выбранные элементы'


def delete_selected(modeladmin, request, queryset):
    """
    Переопределенный action удаления который вызывает .delete() на каждый объект
    чтобы гарантировать мягкое удаление вместо hard delete
    """
    count = 0
    for obj in queryset:
        obj.delete()  # Вызывает delete() метод модели (мягкое удаление)
        count += 1
    modeladmin.message_user(request, f'✓ Удалено {count} элемент(ов).')
delete_selected.short_description = '🗑️ Удалить выбранные элементы'


def hard_delete_selected(modeladmin, request, queryset):
    """
    Action для БЕЗОПАСНОГО полного удаления из БД.
    Удаляет объект только если у него нет опасных связей.

    БЕЗОПАСНЫЕ связи (удаляются вместе с объектом):
    - photos: фотографии объекта (создаются только для этого объекта)

    ОПАСНЫЕ связи (блокируют удаление):
    - kit_items: товар используется в составе комплекта
    - kit_items_direct: товар включен как компонент комплекта
    - ManyToMany: товар связан с другими объектами
    """
    from django.contrib import messages

    items_to_delete = []
    items_with_relations = []

    # Связи которые БЕЗОПАСНО удалять вместе с объектом (они зависят от объекта)
    SAFE_RELATIONS = {'photos'}

    for obj in queryset:
        # Проверяем есть ли опасные связанные объекты
        try:
            has_dangerous_relations = False
            dangerous_relation_details = []

            for relation in obj._meta.get_fields():
                # Пропускаем обычные поля
                if not hasattr(relation, 'related_model'):
                    continue

                # Для reverse relations получаем count
                if hasattr(relation, 'get_accessor_name'):
                    try:
                        accessor_name = relation.get_accessor_name()

                        # Пропускаем безопасные связи (удалятся при cascade delete)
                        if accessor_name in SAFE_RELATIONS:
                            continue

                        related_manager = getattr(obj, accessor_name, None)
                        if related_manager and hasattr(related_manager, 'count'):
                            count = related_manager.count()
                            if count > 0:
                                has_dangerous_relations = True
                                relation_name = relation.related_model.__name__
                                dangerous_relation_details.append(f"{relation_name} ({count})")
                    except (AttributeError, Exception):
                        # Пропускаем ошибки доступа к связям
                        pass

            if has_dangerous_relations:
                details_str = ', '.join(dangerous_relation_details)
                items_with_relations.append(f"{str(obj)} [{details_str}]")
            else:
                items_to_delete.append(obj)
        except Exception as e:
            # На случай любой неожиданной ошибки при проверке
            items_with_relations.append(f"{str(obj)} (ошибка проверки: {str(e)})")

    # Удаляем безопасные элементы
    deleted_count = 0
    for obj in items_to_delete:
        try:
            # ВАЖНО: Сначала явно удаляем все фотографии
            # Это гарантирует что delete() метод каждого фото вызовется
            # и удалит файлы из media/ папки
            # Нужно для всех моделей которые имеют 'photos' связь

            # Для Product/ProductKit/ProductCategory - есть .photos
            if hasattr(obj, 'photos'):
                photos = list(obj.photos.all())  # Получаем копию списка перед удалением
                for photo in photos:
                    photo.delete()  # Вызывает ProductPhoto.delete() который удалит файлы

            # Потом удаляем сам объект
            obj.hard_delete()
            deleted_count += 1
        except Exception as e:
            items_with_relations.append(f"{str(obj)} (ошибка удаления: {str(e)})")

    # Выводим результаты
    if deleted_count > 0:
        modeladmin.message_user(
            request,
            f'✓ Безопасно удалено {deleted_count} элемент(ов) (с фотографиями из media папки).',
            messages.SUCCESS
        )

    if items_with_relations:
        error_msg = f'⚠️ Не удалось удалить {len(items_with_relations)} элемент(ов) (имеют зависимые связи):\n' + '\n'.join(f'  • {item}' for item in items_with_relations)
        modeladmin.message_user(request, error_msg, messages.WARNING)

hard_delete_selected.short_description = '🔴 Безопасно удалить навсегда (только без связей)'


def show_poor_quality_photos(modeladmin, request, queryset):
    """
    Action для фильтрации товаров с фото требующими обновления.
    Перенаправляет на список с применённым фильтром по качеству.
    """
    from django.shortcuts import redirect
    from django.urls import reverse

    model_name = modeladmin.model._meta.model_name
    app_name = modeladmin.model._meta.app_label

    # Перенаправляем на список товаров с фильтром по warning фото
    url = reverse(f'admin:{app_name}_{model_name}_changelist')
    return redirect(f'{url}?photo_quality=warning')
show_poor_quality_photos.short_description = '⚠️ Показать товары с фото требующими обновления'


def show_excellent_quality_photos(modeladmin, request, queryset):
    """
    Action для фильтрации товаров с фото отличного и хорошего качества.
    Перенаправляет на список с применённым фильтром по качеству.
    """
    from django.shortcuts import redirect
    from django.urls import reverse

    model_name = modeladmin.model._meta.model_name
    app_name = modeladmin.model._meta.app_label

    # Перенаправляем на список товаров с фильтром по excellent/good
    url = reverse(f'admin:{app_name}_{model_name}_changelist')
    return redirect(f'{url}?photo_quality=no_warning')
show_excellent_quality_photos.short_description = '✓ Показать товары с хорошим качеством фото'


def show_all_quality_levels(modeladmin, request, queryset):
    """
    Action для показа распределения товаров по качеству фотографий.
    Выводит статистику в сообщении admin.
    """
    from django.contrib import messages
    from django.db.models import Count

    # Получаем статистику по качеству фотографий
    quality_stats = queryset.filter(photos__isnull=False).values(
        'photos__quality_level'
    ).annotate(count=Count('id', distinct=True)).order_by('-count')

    warning_count = queryset.filter(photos__quality_warning=True).distinct().count()
    total_with_photos = queryset.filter(photos__isnull=False).distinct().count()

    if not quality_stats:
        modeladmin.message_user(
            request,
            f'⚠️ В выбранных товарах ({queryset.count()}) нет фотографий.',
            messages.WARNING
        )
        return

    # Формируем сообщение со статистикой
    quality_names = {
        'excellent': '🟢 Отлично',
        'good': '🟡 Хорошо',
        'acceptable': '🟠 Приемлемо',
        'poor': '🔴 Плохо',
        'very_poor': '🔴🔴 Очень плохо',
    }

    stats_text = f'📊 Статистика качества фото в выбранных товарах:\n'
    stats_text += f'Всего товаров с фото: {total_with_photos}\n'
    stats_text += f'Требуют обновления: {warning_count}\n\n'

    for item in quality_stats:
        level = item['photos__quality_level']
        count = item['count']
        label = quality_names.get(level, level)
        stats_text += f'  {label}: {count} товар(ов)\n'

    modeladmin.message_user(request, stats_text, messages.INFO)
show_all_quality_levels.short_description = '📊 Показать статистику качества фото'


def disable_delete_selected(admin_class):
    """
    Декоратор для отключения стандартного Django delete_selected action.
    Наш custom delete_selected будет использоваться вместо него.
    """
    admin_class.actions = [action for action in admin_class.actions
                          if action.__name__ != 'delete_selected']
    return admin_class


@admin.register(ProductVariantGroup)
class ProductVariantGroupAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    list_display = ['name', 'get_products_count', 'created_at']
    search_fields = ['name', 'description']
    list_filter = ['created_at']
    readonly_fields = ['created_at', 'updated_at']

    def get_products_count(self, obj):
        return obj.products.count()
    get_products_count.short_description = 'Товаров'


class ProductCategoryAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    list_display = ('photo_with_quality', 'name', 'sku', 'slug', 'parent', 'is_active', 'get_deleted_status')
    list_filter = (DeletedFilter, 'is_active', QualityLevelFilter, 'parent')
    prepopulated_fields = {'slug': ('name',)}
    search_fields = ('name', 'sku')
    readonly_fields = ('photo_preview_large', 'deleted_at', 'deleted_by')
    actions = [
        restore_items,
        delete_selected,
        hard_delete_selected,
        show_poor_quality_photos,
        show_excellent_quality_photos,
        show_all_quality_levels,
    ]

    def get_queryset(self, request):
        """Переопределяем queryset для доступа ко всем категориям (включая удаленные)"""
        qs = ProductCategory.all_objects.all()
        ordering = self.get_ordering(request)
        if ordering:
            qs = qs.order_by(*ordering)
        return qs

    def get_deleted_status(self, obj):
        """Показывает статус удаления"""
        if obj.is_deleted:
            return format_html(
                '<span style="color: red; font-weight: bold;">🗑️ Удалена</span>'
            )
        return format_html('<span style="color: green;">✓ Активна</span>')
    get_deleted_status.short_description = 'Статус'

    def photo_with_quality(self, obj):
        """Превью фото с индикатором качества в списке категорий"""
        first_photo = obj.photos.first()
        if not first_photo or not first_photo.image:
            return format_html('<span style="color: #999;">Нет фото</span>')

        quality_indicator = format_quality_badge(first_photo.quality_level, show_icon=True)

        return format_html(
            '<div style="display: flex; align-items: center; gap: 8px;">'
            '<img src="{}" style="width: 50px; height: 50px; object-fit: cover; border-radius: 4px;" />'
            '{}'
            '</div>',
            first_photo.image.url,
            quality_indicator
        )
    photo_with_quality.short_description = "Фото"

    def photo_preview(self, obj):
        """Превью фото в списке категорий (старый метод, сохранен для совместимости)"""
        first_photo = obj.photos.first()
        if first_photo and first_photo.image:
            return format_html(
                '<img src="{}" style="width: 50px; height: 50px; object-fit: cover; border-radius: 4px;" />',
                first_photo.image.url
            )
        return "Нет фото"
    photo_preview.short_description = "Фото"

    def photo_preview_large(self, obj):
        """Большое превью фото в форме редактирования"""
        first_photo = obj.photos.first()
        if first_photo and first_photo.image:
            return format_html(
                '<img src="{}" style="max-width: 300px; max-height: 300px; border-radius: 8px;" />',
                first_photo.image.url
            )
        return "Нет фото"
    photo_preview_large.short_description = "Превью основного фото"


class ProductTagAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    list_display = ('name', 'slug', 'is_active')
    list_filter = ('is_active',)
    prepopulated_fields = {'slug': ('name',)}
    search_fields = ('name',)


class ProductAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    list_display = ('photo_with_quality', 'name', 'sku', 'get_categories_display', 'cost_price', 'price', 'sale_price', 'get_variant_groups_display', 'get_status_display')
    list_filter = (DeletedFilter, QualityLevelFilter, 'categories', 'tags', 'variant_groups')
    search_fields = ('name', 'sku', 'description', 'search_keywords')
    filter_horizontal = ('categories', 'tags', 'variant_groups')
    readonly_fields = ('photo_preview_large', 'archived_at', 'archived_by', 'cost_price', 'cost_price_details_display')
    autocomplete_fields = ['base_unit', 'external_category']
    actions = [
        restore_items,
        delete_selected,
        hard_delete_selected,
        show_poor_quality_photos,
        show_excellent_quality_photos,
        show_all_quality_levels,
    ]

    fieldsets = (
        ('Основная информация', {
            'fields': ('name', 'sku', 'variant_suffix', 'description', 'short_description', 'categories', 'external_category', 'base_unit', 'price', 'sale_price')
        }),
        ('Себестоимость', {
            'fields': ('cost_price_details_display',),
            'description': 'Себестоимость рассчитывается автоматически на основе партий товара (FIFO метод). Редактировать вручную невозможно.'
        }),
        ('Дополнительно', {
            'fields': ('tags', 'variant_groups', 'status', 'is_new', 'is_popular', 'is_special')
        }),
        ('Архивирование', {
            'fields': ('archived_at', 'archived_by'),
            'classes': ('collapse',),
            'description': 'Информация об архивировании товара (статус "Архивный" или "Снят").'
        }),
        ('Поиск', {
            'fields': ('search_keywords',),
            'classes': ('collapse',),
            'description': 'Поле для улучшенного поиска. Автоматически генерируется при сохранении, но вы можете добавить дополнительные ключевые слова (синонимы, альтернативные названия и т.д.).'
        }),
        ('Фото', {
            'fields': ('photo_preview_large',),
            'classes': ('collapse',),
        }),
    )

    def cost_price_details_display(self, obj):
        """
        Отображает детали расчета себестоимости товара в админ-панели.
        Показывает: текущая себестоимость, количество партий, их цены и даты.
        """
        from django.utils.html import format_html
        from decimal import Decimal

        # Получаем детали стоимости
        details = obj.cost_price_details

        if not details or not details.get('batches'):
            return format_html(
                '<div style="padding: 12px; background-color: #f9f9f9; border-radius: 4px; border-left: 4px solid #ffc107;">'
                '<strong>Нет партий</strong><br/>'
                '<span style="color: #666;">Себестоимость установится при поступлении первой партии товара</span>'
                '</div>'
            )

        # Текущая себестоимость
        current_cost = details.get('cached_cost', Decimal('0'))
        calculated_cost = details.get('calculated_cost', Decimal('0'))
        total_qty = details.get('total_quantity', Decimal('0'))
        is_synced = details.get('is_synced', True)
        batches = details.get('batches', [])

        # Статус синхронизации
        sync_status = '✓ Синхронизирована' if is_synced else '⚠️ Несинхронизирована'
        sync_color = '#28a745' if is_synced else '#dc3545'

        # HTML для партий
        batches_html = '<div style="margin-top: 10px;"><strong style="font-size: 13px;">Партии:</strong><ul style="margin: 5px 0; padding-left: 20px;">'
        for batch in batches:
            batches_html += (
                f'<li style="font-size: 12px; margin: 3px 0;">'
                f'{batch.get("warehouse_name", "—")} | '
                f'Кол-во: {batch.get("quantity", 0)} | '
                f'Цена: {batch.get("cost_price", 0)} руб. | '
                f'Дата: {batch.get("created_at", "—")}'
                f'</li>'
            )
        batches_html += '</ul></div>'

        return format_html(
            '<div style="padding: 12px; background-color: #f9f9f9; border-radius: 4px; border-left: 4px solid #28a745;">'
            '<div><strong style="font-size: 14px;">Текущая себестоимость:</strong> <span style="font-size: 16px; color: #28a745; font-weight: bold;">{} руб.</span></div>'
            '<div style="margin-top: 8px; font-size: 12px; color: #666;">'
            'Статус: <span style="color: {}; font-weight: bold;">{}</span><br/>'
            'Всего в партиях: {} шт.<br/>'
            'Рассчитанная: {} руб.'
            '</div>'
            '{}'
            '<div style="margin-top: 8px; font-size: 11px; color: #999;">'
            'Себестоимость рассчитывается автоматически при поступлении товара (FIFO метод).<br/>'
            'Редактировать вручную невозможно.'
            '</div>'
            '</div>',
            current_cost,
            sync_color,
            sync_status,
            total_qty,
            calculated_cost,
            batches_html
        )
    cost_price_details_display.short_description = 'Себестоимость товара'

    def get_queryset(self, request):
        """Переопределяем queryset для доступа ко всем товарам"""
        qs = super().get_queryset(request)
        ordering = self.get_ordering(request)
        if ordering:
            qs = qs.order_by(*ordering)
        return qs

    def get_status_display(self, obj):
        """Показывает статус товара"""
        status_colors = {
            'active': ('green', '✓ Активный'),
            'archived': ('orange', '📦 Архивный'),
            'discontinued': ('red', '🗑️ Снят'),
        }
        color, label = status_colors.get(obj.status, ('gray', obj.status))
        return format_html(
            '<span style="color: {}; font-weight: bold;">{}</span>',
            color, label
        )
    get_status_display.short_description = 'Статус'

    def get_categories_display(self, obj):
        categories = obj.categories.all()[:3]
        if not categories:
            return "-"
        result = ", ".join([cat.name for cat in categories])
        if obj.categories.count() > 3:
            result += f" (+{obj.categories.count() - 3})"
        return result
    get_categories_display.short_description = 'Категории'

    def get_variant_groups_display(self, obj):
        groups = obj.variant_groups.all()[:3]
        if not groups:
            return "-"
        result = ", ".join([g.name for g in groups])
        if obj.variant_groups.count() > 3:
            result += f" (+{obj.variant_groups.count() - 3})"
        return result
    get_variant_groups_display.short_description = 'Группы вариантов'

    def photo_with_quality(self, obj):
        """Превью фото с индикатором качества в списке товаров"""
        first_photo = obj.photos.first()
        if not first_photo or not first_photo.image:
            return format_html('<span style="color: #999;">Нет фото</span>')

        # Показываем фото с индикатором качества справа
        quality_indicator = format_quality_badge(first_photo.quality_level, show_icon=True)

        return format_html(
            '<div style="display: flex; align-items: center; gap: 8px;">'
            '<img src="{}" style="width: 50px; height: 50px; object-fit: cover; border-radius: 4px;" />'
            '{}'
            '</div>',
            first_photo.image.url,
            quality_indicator
        )
    photo_with_quality.short_description = "Фото"

    def photo_preview(self, obj):
        """Превью фото в списке товаров (старый метод, сохранен для совместимости)"""
        first_photo = obj.photos.first()
        if first_photo and first_photo.image:
            return format_html(
                '<img src="{}" style="width: 50px; height: 50px; object-fit: cover; border-radius: 4px;" />',
                first_photo.image.url
            )
        return "Нет фото"
    photo_preview.short_description = "Фото"

    def photo_preview_large(self, obj):
        """Большое превью фото в форме редактирования"""
        first_photo = obj.photos.first()
        if first_photo and first_photo.image:
            return format_html(
                '<img src="{}" style="max-width: 300px; max-height: 300px; border-radius: 8px;" />',
                first_photo.image.url
            )
        return "Нет фото"
    photo_preview_large.short_description = "Превью основного фото"


class ProductKitAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    list_display = ('photo_with_quality', 'name', 'slug', 'get_categories_display', 'get_price_display', 'is_temporary', 'get_order_link', 'get_status_display')
    list_filter = (DeletedFilter, 'is_temporary', QualityLevelFilter, 'categories', 'tags')
    prepopulated_fields = {'slug': ('name',)}
    filter_horizontal = ('categories', 'tags')
    readonly_fields = ('photo_preview_large', 'base_price', 'archived_at', 'archived_by', 'order')
    autocomplete_fields = ['external_category']
    actions = [
        show_poor_quality_photos,
        show_excellent_quality_photos,
        show_all_quality_levels,
    ]

    fieldsets = (
        ('Основная информация', {
            'fields': ('name', 'sku', 'slug', 'description', 'short_description', 'categories', 'external_category')
        }),
        ('Ценообразование', {
            'fields': ('base_price', 'price', 'sale_price', 'price_adjustment_type', 'price_adjustment_value'),
            'description': 'base_price - сумма цен компонентов (вычисляется автоматически). price - итоговая цена с учетом корректировок. sale_price - цена со скидкой (опционально).'
        }),
        ('Временный комплект', {
            'fields': ('is_temporary', 'order'),
            'description': 'Временные комплекты создаются для конкретных заказов и не показываются в каталоге.'
        }),
        ('Дополнительно', {
            'fields': ('tags', 'status', 'is_new', 'is_popular', 'is_special')
        }),
        ('Архивирование', {
            'fields': ('archived_at', 'archived_by'),
            'classes': ('collapse',),
            'description': 'Информация об архивировании комплекта (статус "Архивный" или "Снят").'
        }),
        ('Фото', {
            'fields': ('photo_preview_large',),
            'classes': ('collapse',),
        }),
    )

    def get_price_display(self, obj):
        """Отображение финальной цены комплекта"""
        try:
            return f"{obj.actual_price} руб."
        except Exception:
            return "-"
    get_price_display.short_description = "Цена"

    def get_order_link(self, obj):
        """Отображение ссылки на заказ для временных комплектов"""
        if obj.order:
            from django.urls import reverse
            url = reverse('admin:orders_order_change', args=[obj.order.pk])
            return format_html('<a href="{}">{}</a>', url, obj.order.order_number)
        return '-'
    get_order_link.short_description = "Заказ"

    def get_queryset(self, request):
        """Переопределяем queryset для доступа ко всем комплектам"""
        qs = super().get_queryset(request)
        ordering = self.get_ordering(request)
        if ordering:
            qs = qs.order_by(*ordering)
        return qs

    def get_status_display(self, obj):
        """Показывает статус комплекта"""
        status_colors = {
            'active': ('green', '✓ Активный'),
            'archived': ('orange', '📦 Архивный'),
            'discontinued': ('red', '🗑️ Снят'),
        }
        color, label = status_colors.get(obj.status, ('gray', obj.status))
        return format_html(
            '<span style="color: {}; font-weight: bold;">{}</span>',
            color, label
        )
    get_status_display.short_description = 'Статус'

    def get_categories_display(self, obj):
        categories = obj.categories.all()[:3]
        if not categories:
            return "-"
        result = ", ".join([cat.name for cat in categories])
        if obj.categories.count() > 3:
            result += f" (+{obj.categories.count() - 3})"
        return result
    get_categories_display.short_description = 'Категории'

    def photo_with_quality(self, obj):
        """Превью фото с индикатором качества в списке комплектов"""
        first_photo = obj.photos.first()
        if not first_photo or not first_photo.image:
            return format_html('<span style="color: #999;">Нет фото</span>')

        quality_indicator = format_quality_badge(first_photo.quality_level, show_icon=True)

        return format_html(
            '<div style="display: flex; align-items: center; gap: 8px;">'
            '<img src="{}" style="width: 50px; height: 50px; object-fit: cover; border-radius: 4px;" />'
            '{}'
            '</div>',
            first_photo.image.url,
            quality_indicator
        )
    photo_with_quality.short_description = "Фото"

    def photo_preview(self, obj):
        """Превью фото в списке комплектов (старый метод, сохранен для совместимости)"""
        first_photo = obj.photos.first()
        if first_photo and first_photo.image:
            return format_html(
                '<img src="{}" style="width: 50px; height: 50px; object-fit: cover; border-radius: 4px;" />',
                first_photo.image.url
            )
        return "Нет фото"
    photo_preview.short_description = "Фото"

    def photo_preview_large(self, obj):
        """Большое превью фото в форме редактирования"""
        first_photo = obj.photos.first()
        if first_photo and first_photo.image:
            return format_html(
                '<img src="{}" style="max-width: 300px; max-height: 300px; border-radius: 8px;" />',
                first_photo.image.url
            )
        return "Нет фото"
    photo_preview_large.short_description = "Превью основного фото"


class KitItemPriorityInline(nested_admin.NestedTabularInline):
    model = KitItemPriority
    extra = 0  # Не показывать пустые формы
    fields = ['product', 'priority']
    autocomplete_fields = ['product']

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.select_related('product')

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        """Показывать только товары из выбранной группы вариантов"""
        if db_field.name == "product":
            # Получаем kit_item из родительского объекта через request
            # Это будет работать автоматически с nested_admin
            pass
        return super().formfield_for_foreignkey(db_field, request, **kwargs)


class KitItemInline(nested_admin.NestedStackedInline):
    model = KitItem
    extra = 0  # Не показывать пустые формы
    fields = ['product', 'variant_group', 'quantity']
    autocomplete_fields = ['product']
    inlines = [KitItemPriorityInline]

    class Media:
        css = {
            'all': ('admin/css/custom_nested.css',)
        }


class ProductPhotoInline(admin.TabularInline):
    model = ProductPhoto
    extra = 1
    readonly_fields = ('image_preview', 'quality_display')
    fields = ('image', 'image_preview', 'quality_display', 'order')

    def image_preview(self, obj):
        """Превью основного фото (большой размер 800×800)"""
        if obj.image:
            return format_html(
                '<img src="{}" style="max-width: 250px; max-height: 250px; border-radius: 4px;" />',
                obj.get_large_url()
            )
        return "Нет изображения"
    image_preview.short_description = "Превью"

    def quality_display(self, obj):
        """Отображение качества фото в inline таблице"""
        if not obj.pk:
            return format_html('<span style="color: #999;">Сохраните фото</span>')
        return format_quality_display(
            obj.quality_level,
            width=getattr(obj, 'width', None),
            height=getattr(obj, 'height', None),
            warning=obj.quality_warning
        )
    quality_display.short_description = "Качество"

class ProductKitPhotoInline(nested_admin.NestedTabularInline):
    model = ProductKitPhoto
    extra = 0  # Не показывать пустые формы
    readonly_fields = ('image_preview', 'quality_display')
    fields = ('image', 'image_preview', 'quality_display', 'order')

    def image_preview(self, obj):
        """Превью основного фото (большой размер 800×800)"""
        if obj.image:
            return format_html(
                '<img src="{}" style="max-width: 250px; max-height: 250px; border-radius: 4px;" />',
                obj.get_large_url()
            )
        return "Нет изображения"
    image_preview.short_description = "Превью"

    def quality_display(self, obj):
        """Отображение качества фото в inline таблице"""
        if not obj.pk:
            return format_html('<span style="color: #999;">Сохраните фото</span>')
        return format_quality_display(
            obj.quality_level,
            width=getattr(obj, 'width', None),
            height=getattr(obj, 'height', None),
            warning=obj.quality_warning
        )
    quality_display.short_description = "Качество"

class ProductCategoryPhotoInline(admin.TabularInline):
    model = ProductCategoryPhoto
    extra = 1
    readonly_fields = ('image_preview', 'quality_display')
    fields = ('image', 'image_preview', 'quality_display', 'order')

    def image_preview(self, obj):
        """Превью основного фото (большой размер 800×800)"""
        if obj.image:
            return format_html(
                '<img src="{}" style="max-width: 250px; max-height: 250px; border-radius: 4px;" />',
                obj.get_large_url()
            )
        return "Нет изображения"
    image_preview.short_description = "Превью"

    def quality_display(self, obj):
        """Отображение качества фото в inline таблице"""
        if not obj.pk:
            return format_html('<span style="color: #999;">Сохраните фото</span>')
        return format_quality_display(
            obj.quality_level,
            width=getattr(obj, 'width', None),
            height=getattr(obj, 'height', None),
            warning=obj.quality_warning
        )
    quality_display.short_description = "Качество"


class ProductSalesUnitInline(admin.TabularInline):
    """Инлайн для единиц продажи товара"""
    model = ProductSalesUnit
    extra = 0
    fields = (
        'name', 'conversion_factor', 'price', 'sale_price',
        'min_quantity', 'quantity_step', 'is_default', 'is_active'
    )
    verbose_name = "Единица продажи"
    verbose_name_plural = "Единицы продажи"


class ProductKitAdminWithItems(ProductKitAdmin):
    inlines = [KitItemInline]


# Update admin classes to include photo inlines
class ProductAdminWithPhotos(ProductAdmin):
    inlines = [ProductPhotoInline, ProductSalesUnitInline]

class ProductKitAdminWithItemsAndPhotos(nested_admin.NestedModelAdmin, ProductKitAdmin):
    inlines = [KitItemInline, ProductKitPhotoInline]

class ProductCategoryAdminWithPhotos(ProductCategoryAdmin):
    inlines = [ProductCategoryPhotoInline]


@admin.register(KitItem)
class KitItemAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    list_display = ['__str__', 'kit', 'get_type', 'quantity', 'has_priorities']
    list_filter = ['kit']
    list_select_related = ['kit', 'product', 'variant_group']
    inlines = [KitItemPriorityInline]
    fields = ['kit', 'product', 'variant_group', 'quantity']

    def get_type(self, obj):
        if obj.variant_group:
            return format_html('<span style="color: #0066cc;">Группа: {}</span>', obj.variant_group.name)
        return f"Товар: {obj.product.name if obj.product else '-'}"
    get_type.short_description = 'Тип'

    def has_priorities(self, obj):
        return obj.priorities.exists()
    has_priorities.boolean = True
    has_priorities.short_description = 'Приоритеты настроены'


@admin.register(SKUCounter)
class SKUCounterAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    list_display = ['counter_type', 'current_value', 'get_next_preview']
    list_filter = ['counter_type']
    readonly_fields = ['get_next_preview']

    def get_next_preview(self, obj):
        """Показывает, каким будет следующий артикул"""
        next_val = obj.current_value + 1
        if obj.counter_type == 'product':
            return format_html('<strong>PROD-{:06d}</strong>', next_val)
        elif obj.counter_type == 'kit':
            return format_html('<strong>KIT-{:06d}</strong>', next_val)
        elif obj.counter_type == 'category':
            return format_html('<strong>CAT-{:04d}</strong>', next_val)
        return str(next_val)
    get_next_preview.short_description = 'Следующий артикул'

    def has_delete_permission(self, request, obj=None):
        # Запрещаем удаление счетчиков
        return False


@admin.register(CostPriceHistory)
class CostPriceHistoryAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    list_display = ['product', 'get_price_change', 'reason', 'created_at']
    list_filter = ['reason', 'created_at', 'product']
    search_fields = ['product__name', 'product__sku', 'notes']
    readonly_fields = ['product', 'old_cost_price', 'new_cost_price', 'reason', 'related_object_id', 'related_object_type', 'notes', 'created_at']
    date_hierarchy = 'created_at'

    fieldsets = (
        ('Информация о изменении', {
            'fields': ('product', 'reason', 'created_at')
        }),
        ('Себестоимость', {
            'fields': ('old_cost_price', 'new_cost_price', 'get_price_change')
        }),
        ('Связанные объекты', {
            'fields': ('related_object_type', 'related_object_id'),
            'classes': ('collapse',),
        }),
        ('Примечания', {
            'fields': ('notes',),
            'classes': ('collapse',),
        }),
    )

    def get_price_change(self, obj):
        """Показывает изменение цены в красивом формате"""
        change = obj.new_cost_price - obj.old_cost_price
        change_percent = (change / obj.old_cost_price * 100) if obj.old_cost_price != 0 else 0

        if change > 0:
            color = '#dc3545'  # red
            symbol = '↑'
        elif change < 0:
            color = '#28a745'  # green
            symbol = '↓'
        else:
            color = '#6c757d'  # gray
            symbol = '='

        return format_html(
            '<span style="color: {}; font-weight: bold;">{} {} {:.2f} руб. ({:+.2f}%)</span>',
            color,
            symbol,
            obj.old_cost_price,
            abs(change),
            change_percent
        )
    get_price_change.short_description = 'Изменение'

    def has_delete_permission(self, request, obj=None):
        # История не должна удаляться вручную
        return False

    def has_add_permission(self, request):
        # История создается только автоматически через сигналы
        return False


# === Админка для единиц измерения ===

@admin.register(UnitOfMeasure)
class UnitOfMeasureAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    """Админка для справочника единиц измерения"""
    list_display = ('code', 'name', 'short_name', 'position', 'is_active')
    list_filter = ('is_active',)
    search_fields = ('code', 'name', 'short_name')
    list_editable = ('position', 'is_active')
    ordering = ('position', 'code')

    fieldsets = (
        ('Основная информация', {
            'fields': ('code', 'name', 'short_name')
        }),
        ('Настройки', {
            'fields': ('position', 'is_active')
        }),
    )


@admin.register(ProductSalesUnit)
class ProductSalesUnitAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    """Админка для единиц продажи товаров"""
    list_display = (
        'product', 'name', 'conversion_factor',
        'get_price_display', 'min_quantity', 'is_default', 'is_active'
    )
    list_filter = ('is_active', 'is_default')
    search_fields = ('product__name', 'product__sku', 'name')
    autocomplete_fields = ['product']
    list_editable = ('is_default', 'is_active')
    ordering = ('product', 'position')

    fieldsets = (
        ('Товар и название', {
            'fields': ('product', 'name')
        }),
        ('Конверсия', {
            'fields': ('conversion_factor',),
            'description': 'Сколько единиц продажи получается из 1 базовой единицы товара. '
                          'Например: 1 банч = 15 веток → conversion_factor = 15'
        }),
        ('Ценообразование', {
            'fields': ('price', 'sale_price'),
            'description': 'Цена за единицу продажи. sale_price - цена со скидкой (опционально).'
        }),
        ('Ограничения', {
            'fields': ('min_quantity', 'quantity_step'),
            'description': 'min_quantity - минимальное количество для заказа. '
                          'quantity_step - шаг изменения количества.'
        }),
        ('Настройки', {
            'fields': ('position', 'is_default', 'is_active')
        }),
    )

    def get_price_display(self, obj):
        """Отображение цены с учетом скидки"""
        if obj.sale_price:
            return format_html(
                '<span style="text-decoration: line-through; color: #999;">{}</span> '
                '<span style="color: #dc3545; font-weight: bold;">{}</span>',
                obj.price, obj.sale_price
            )
        return obj.price
    get_price_display.short_description = 'Цена'


admin.site.register(ProductCategory, ProductCategoryAdminWithPhotos)
admin.site.register(ProductTag, ProductTagAdmin)
admin.site.register(Product, ProductAdminWithPhotos)
admin.site.register(ProductKit, ProductKitAdminWithItemsAndPhotos)


# === Админка для ConfigurableProduct ===

class ConfigurableProductOptionInline(admin.TabularInline):
    """Инлайн для вариантов вариативного товара"""
    model = ConfigurableProductOption
    extra = 0
    fields = ('kit', 'product', 'variant_sku', 'is_default', 'attributes')
    readonly_fields = ('variant_sku',)
    verbose_name = "Вариант"
    verbose_name_plural = "Варианты"


class ConfigurableProductAttributeInline(admin.TabularInline):
    """Инлайн для атрибутов родительского товара"""
    model = ConfigurableProductAttribute
    extra = 0
    fields = ('name', 'option', 'kit', 'product', 'position', 'visible')
    verbose_name = "Атрибут"
    verbose_name_plural = "Атрибуты"


@admin.register(ConfigurableProduct)
class ConfigurableProductAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    """Админка для вариативных товаров"""
    list_display = ('name', 'sku', 'status', 'get_options_count', 'created_at')
    list_filter = ('status', 'created_at')
    search_fields = ('name', 'sku', 'description')
    readonly_fields = ('created_at', 'updated_at', 'slug')
    inlines = [ConfigurableProductOptionInline, ConfigurableProductAttributeInline]
    autocomplete_fields = ['external_category']

    fieldsets = (
        ('Основная информация', {
            'fields': ('name', 'sku', 'slug', 'status', 'external_category')
        }),
        ('Описание', {
            'fields': ('short_description', 'description')
        }),
        ('Служебная информация', {
            'fields': ('created_at', 'updated_at'),
            'classes': ('collapse',)
        }),
    )
    
    def get_options_count(self, obj):
        """Количество вариантов"""
        count = obj.options.count()
        return format_html(
            '<span style="font-weight: bold; color: {};">{}</span>',
            '#28a745' if count > 0 else '#6c757d',
            count
        )
    get_options_count.short_description = 'Вариантов'


@admin.register(BouquetName)
class BouquetNameAdmin(TenantAdminOnlyMixin, admin.ModelAdmin):
    """
    Административный интерфейс для управления названиями букетов
    """
    list_display = ('name', 'language', 'is_approved', 'usage_count', 'generated_at')
    list_filter = ('language', 'is_approved')
    search_fields = ('name',)
    filter_horizontal = ('color_tags', 'occasion_tags', 'style_tags')
    actions = ['approve_selected', 'reject_selected']
    
    fieldsets = (
        ('Основная информация', {
            'fields': ('name', 'language', 'is_approved')
        }),
        ('Теги', {
            'fields': ('color_tags', 'occasion_tags', 'style_tags')
        }),
        ('Статистика', {
            'fields': ('usage_count', 'generated_at', 'approved_at')
        }),
    )
    
    readonly_fields = ('usage_count', 'generated_at', 'approved_at')
    
    def approve_selected(self, request, queryset):
        from django.db import models
        queryset.update(is_approved=True, approved_at=models.DateTimeField(auto_now=True))
        self.message_user(request, "Выбранные названия были одобрены")
    
    approve_selected.short_description = "Одобрить выбранные названия"
    
    def reject_selected(self, request, queryset):
        queryset.update(is_approved=False, approved_at=None)
        self.message_user(request, "Выбранные названия были отклонены")
    
    reject_selected.short_description = "Отклонить выбранные названия"
