"""
Модели категорий и тегов для товаров и комплектов.
"""
from django.db import models
from django.db.models import Q
from django.utils import timezone
from django.core.exceptions import ValidationError

from .managers import ActiveManager, SoftDeleteManager, SoftDeleteQuerySet
from ..services.slug_service import SlugService


class ProductCategory(models.Model):
    """
    Категории товаров и комплектов (поддержка нескольких уровней не обязательна, но возможна позже).
    """
    name = models.CharField(max_length=200, verbose_name="Название")
    sku = models.CharField(max_length=100, blank=True, null=True, unique=True, verbose_name="Артикул", db_index=True)
    slug = models.SlugField(max_length=200, unique=True, blank=True, verbose_name="URL-идентификатор")
    parent = models.ForeignKey('self', on_delete=models.SET_NULL, null=True, blank=True,
                              related_name='children', verbose_name="Родительская категория")
    is_active = models.BooleanField(default=True, verbose_name="Активна")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания", null=True)
    updated_at = models.DateTimeField(auto_now=True, verbose_name="Дата обновления", null=True)

    # Поля для мягкого удаления
    is_deleted = models.BooleanField(default=False, verbose_name="Удалена", db_index=True)
    deleted_at = models.DateTimeField(null=True, blank=True, verbose_name="Время удаления")
    deleted_by = models.ForeignKey(
        'accounts.CustomUser',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='deleted_categories',
        verbose_name="Удалена пользователем"
    )

    objects = SoftDeleteManager.from_queryset(SoftDeleteQuerySet)()  # Менеджер по умолчанию (исключает удаленные)
    all_objects = models.Manager()  # Менеджер для доступа ко ВСЕМ объектам (включая удаленные)
    active = ActiveManager()  # Кастомный менеджер для активных категорий

    class Meta:
        verbose_name = "Категория товара"
        verbose_name_plural = "Категории товаров"
        indexes = [
            models.Index(fields=['is_active']),
            models.Index(fields=['is_deleted']),
            models.Index(fields=['is_deleted', 'created_at']),
        ]
        constraints = [
            # Уникальное имя для активных категорий (исключаем удалённые)
            models.UniqueConstraint(
                fields=['name'],
                condition=Q(is_deleted=False),
                name='unique_active_category_name'
            ),
        ]

    def __str__(self):
        return self.name

    @property
    def main_photo(self):
        """
        Главное фото категории (is_main=True).
        Используется в карточках, каталоге, превью.
        
        Returns:
            ProductCategoryPhoto | None: Главное фото или None если фото нет
        """
        return self.photos.filter(is_main=True).first()

    def clean(self):
        """Валидация категории перед сохранением"""
        # 1. Защита от самоссылки
        if self.parent and self.parent.pk == self.pk:
            raise ValidationError({
                'parent': 'Категория не может быть родителем самой себя.'
            })

        # 2. Защита от циклических ссылок (только для существующих категорий)
        if self.parent and self.pk:
            self._check_parent_chain()

        # 3. Проверка активности родителя
        if self.parent and not self.parent.is_active:
            raise ValidationError({
                'parent': 'Нельзя выбрать неактивную категорию в качестве родителя.'
            })

    def _check_parent_chain(self):
        """Проверяет цепочку родителей на циклы и глубину вложенности"""
        from django.conf import settings

        current = self.parent
        depth = 0
        max_depth = getattr(settings, 'MAX_CATEGORY_DEPTH', 10)

        while current:
            if current.pk == self.pk:
                raise ValidationError({
                    'parent': f'Обнаружена циклическая ссылка. '
                            f'Категория "{self.name}" не может быть потомком самой себя.'
                })

            depth += 1
            if depth > max_depth:
                raise ValidationError({
                    'parent': f'Слишком глубокая вложенность категорий '
                            f'(максимум {max_depth} уровней).'
                })

            current = current.parent

    def save(self, *args, **kwargs):
        # Вызываем валидацию перед сохранением
        self.full_clean()

        # Автоматическая генерация slug из названия с транслитерацией
        if not self.slug or self.slug.strip() == '':
            self.slug = SlugService.generate_unique_slug(self.name, ProductCategory, self.pk)

        # Автоматическая генерация артикула при создании новой категории
        if not self.sku and not self.pk:
            from ..utils.sku_generator import generate_category_sku
            self.sku = generate_category_sku()

        super().save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        """Soft delete вместо hard delete - марк как удаленный"""
        self.is_deleted = True
        self.deleted_at = timezone.now()
        self.save(update_fields=['is_deleted', 'deleted_at'])
        # Возвращаем результат в формате Django
        return 1, {self.__class__._meta.label: 1}

    def hard_delete(self):
        """Полное удаление из БД (необратимо!)"""
        super().delete()


class ProductTag(models.Model):
    """
    Свободные теги для фильтрации и поиска.
    """
    name = models.CharField(max_length=100, verbose_name="Название")
    slug = models.SlugField(max_length=100, unique=True, verbose_name="URL-идентификатор")
    is_active = models.BooleanField(default=True, verbose_name="Активен", db_index=True)
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания", null=True)
    updated_at = models.DateTimeField(auto_now=True, verbose_name="Дата обновления", null=True)

    objects = models.Manager()
    active = ActiveManager()

    class Meta:
        verbose_name = "Тег товара"
        verbose_name_plural = "Теги товаров"
        indexes = [
            models.Index(fields=['is_active']),
        ]
        constraints = [
            # Уникальное имя для активных тегов (неактивные могут быть переиспользованы)
            models.UniqueConstraint(
                fields=['name'],
                condition=Q(is_active=True),
                name='unique_active_tag_name'
            ),
        ]

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = SlugService.generate_unique_slug(self.name, ProductTag, self.pk)
        super().save(*args, **kwargs)
