from django import forms
from django.forms import inlineformset_factory
from .models import (
    Product, ProductKit, ProductCategory, ProductTag, ProductPhoto, KitItem,
    ProductKitPhoto, ProductCategoryPhoto, ProductVariantGroup, ProductVariantGroupItem,
    ConfigurableProduct, ConfigurableProductOption, ConfigurableProductAttribute,
    ProductAttribute, ProductAttributeValue, ProductSalesUnit, UnitOfMeasure
)


class SKUUniqueMixin:
    """
    Миксин для валидации уникальности артикула среди всех моделей.
    Проверяет уникальность SKU среди: Product, ProductKit, ProductCategory, ConfigurableProduct.
    Также защищает зарезервированные префиксы от ручного ввода.
    """
    
    # Зарезервированные префиксы для автогенерации
    RESERVED_PREFIXES = {
        'PROD-': 'товаров',
        'KIT-': 'комплектов',
        'CAT-': 'категорий',
        'VAR-': 'вариативных товаров',
    }

    def clean_sku(self):
        """
        Проверяет уникальность артикула среди всех моделей с артикулами.
        Если SKU пустой - пропускаем (будет сгенерирован автоматически).
        Запрещает ручной ввод зарезервированных префиксов.
        """
        sku = self.cleaned_data.get('sku')

        # Пустое значение - ок, будет автогенерация
        if not sku or sku.strip() == '':
            return None

        sku = sku.strip()

        # Проверяем зарезервированные префиксы
        # Но пропускаем проверку, если это редактирование и артикул не изменился
        sku_upper = sku.upper()
        is_existing_sku = self.instance.pk and self.instance.sku == sku

        if not is_existing_sku:
            for prefix, entity_type in self.RESERVED_PREFIXES.items():
                if sku_upper.startswith(prefix):
                    raise forms.ValidationError(
                        f'Префикс "{prefix}" зарезервирован для автоматической генерации артикулов {entity_type}. '
                        f'Пожалуйста, используйте другой артикул или оставьте поле пустым для автогенерации.'
                    )

        # Проверяем во всех моделях
        models_to_check = [
            (Product, 'товар'),
            (ProductKit, 'комплект'),
            (ProductCategory, 'категория'),
            (ConfigurableProduct, 'вариативный товар'),
        ]

        for model, model_name in models_to_check:
            queryset = model.objects.filter(sku=sku)

            # Исключаем текущий объект при редактировании
            if self.instance.pk and isinstance(self.instance, model):
                queryset = queryset.exclude(pk=self.instance.pk)

            if queryset.exists():
                existing = queryset.first()
                raise forms.ValidationError(
                    f'Артикул "{sku}" уже используется в {model_name} "{existing.name}". '
                    f'Пожалуйста, выберите другой артикул.'
                )

        return sku


class ProductForm(SKUUniqueMixin, forms.ModelForm):
    """
    Форма для создания и редактирования товара.
    Поле photos НЕ включено в форму - файлы обрабатываются отдельно в view.
    """
    categories = forms.ModelMultipleChoiceField(
        queryset=ProductCategory.objects.filter(is_active=True),
        widget=forms.CheckboxSelectMultiple,
        required=False,
        label="Категории"
    )

    external_category = forms.ModelChoiceField(
        queryset=ProductCategory.objects.filter(is_active=True),
        required=False,
        empty_label="Не выбрана",
        label="Внешняя категория",
        help_text="Категория для интеграций с внешними площадками (Recommerce, WooCommerce и др.)",
        widget=forms.Select(attrs={'class': 'form-select'})
    )

    tags = forms.ModelMultipleChoiceField(
        queryset=ProductTag.objects.filter(is_active=True),
        widget=forms.CheckboxSelectMultiple,
        required=False,
        label="Теги"
    )

    class Meta:
        model = Product
        fields = [
            'name', 'sku', 'description', 'short_description', 'categories',
            'external_category', 'tags', 'base_unit', 'price', 'sale_price', 'status',
            'is_new', 'is_popular', 'is_special'
        ]
        labels = {
            'name': 'Название',
            'sku': 'Артикул',
            'description': 'Описание',
            'short_description': 'Краткое описание',
            'categories': 'Категории',
            'tags': 'Теги',
            'base_unit': 'Единица измерения',
            'price': 'Основная цена',
            'sale_price': 'Цена со скидкой',
            'status': 'Статус'
        }
        widgets = {
            'base_unit': forms.Select(attrs={'class': 'form-control'}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Make fields more user-friendly
        self.fields['name'].widget.attrs.update({
            'class': 'form-control form-control-lg fw-semibold',
            'placeholder': 'Введите название товара'
        })
        self.fields['sku'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Артикул (необязательно, будет сгенерирован автоматически)'
        })
        self.fields['description'].widget.attrs.update({
            'class': 'form-control',
            'rows': 3
        })
        self.fields['short_description'].widget.attrs.update({
            'class': 'form-control',
            'rows': 2,
            'placeholder': 'Краткое описание для превью и площадок'
        })
        self.fields['price'].widget.attrs.update({'class': 'form-control'})
        self.fields['sale_price'].widget.attrs.update({'class': 'form-control'})
        self.fields['base_unit'].widget.attrs.update({'class': 'form-control'})
        self.fields['status'].widget.attrs.update({'class': 'form-control'})

        # Фильтруем только активные единицы измерения
        from .models import UnitOfMeasure
        self.fields['base_unit'].queryset = UnitOfMeasure.objects.filter(
            is_active=True
        ).order_by('position', 'code')
        self.fields['base_unit'].required = True
        self.fields['base_unit'].help_text = 'Базовая единица хранения и закупки. На её основе создаются единицы продажи.'

        # Маркетинговые флаги (switch-стиль)
        for flag_field in ['is_new', 'is_popular', 'is_special']:
            self.fields[flag_field].widget.attrs.update({
                'class': 'form-check-input',
                'role': 'switch'
            })

    def clean_name(self):
        """Валидация уникальности имени для активных товаров"""
        name = self.cleaned_data.get('name')

        if name:
            # Проверяем уникальность имени среди активных товаров
            # Исключаем текущий товар при редактировании (self.instance.pk)
            existing = Product.objects.filter(
                name=name,
                status='active'
            )

            if self.instance.pk:
                existing = existing.exclude(pk=self.instance.pk)

            if existing.exists():
                raise forms.ValidationError(
                    f'Товар с названием "{name}" уже существует. '
                    f'Пожалуйста, используйте другое название.'
                )

        return name


class ProductKitForm(SKUUniqueMixin, forms.ModelForm):
    """
    Форма для создания и редактирования комплекта.
    Цена комплекта вычисляется автоматически из цен компонентов.
    """
    categories = forms.ModelMultipleChoiceField(
        queryset=ProductCategory.objects.filter(is_active=True),
        widget=forms.CheckboxSelectMultiple,
        required=False,
        label="Категории"
    )

    external_category = forms.ModelChoiceField(
        queryset=ProductCategory.objects.filter(is_active=True),
        required=False,
        empty_label="Не выбрана",
        label="Внешняя категория",
        help_text="Категория для интеграций с внешними площадками (Recommerce, WooCommerce и др.)",
        widget=forms.Select(attrs={'class': 'form-select'})
    )

    tags = forms.ModelMultipleChoiceField(
        queryset=ProductTag.objects.filter(is_active=True),
        widget=forms.CheckboxSelectMultiple,
        required=False,
        label="Теги"
    )

    class Meta:
        model = ProductKit
        fields = [
            'name', 'sku', 'description', 'short_description', 'categories',
            'external_category', 'tags', 'sale_price', 'price_adjustment_type', 'price_adjustment_value', 'status'
        ]
        labels = {
            'name': 'Название',
            'sku': 'Артикул',
            'description': 'Описание',
            'short_description': 'Краткое описание',
            'categories': 'Категории',
            'tags': 'Теги',
            'sale_price': 'Цена со скидкой',
            'price_adjustment_type': 'Как изменить итоговую цену',
            'price_adjustment_value': 'Значение корректировки',
            'status': 'Статус'
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Make fields more user-friendly
        self.fields['name'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Введите название комплекта'
        })
        self.fields['sku'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Артикул (необязательно, будет сгенерирован автоматически)'
        })
        self.fields['description'].widget.attrs.update({
            'class': 'form-control',
            'rows': 3
        })
        self.fields['short_description'].widget.attrs.update({
            'class': 'form-control',
            'rows': 2,
            'placeholder': 'Краткое описание для превью и площадок'
        })
        self.fields['sale_price'].widget.attrs.update({'class': 'form-control'})
        self.fields['price_adjustment_type'].widget.attrs.update({'class': 'form-control'})
        self.fields['price_adjustment_value'].widget.attrs.update({
            'class': 'form-control',
            'step': '0.01',
            'placeholder': '0'
        })
        self.fields['status'].widget.attrs.update({'class': 'form-control'})

    def clean_name(self):
        """Валидация уникальности имени для активных комплектов"""
        name = self.cleaned_data.get('name')

        if name:
            existing = ProductKit.objects.filter(
                name=name,
                status='active',
                is_temporary=False
            )

            if self.instance.pk:
                existing = existing.exclude(pk=self.instance.pk)

            if existing.exists():
                raise forms.ValidationError(
                    f'Комплект с названием "{name}" уже существует. '
                    f'Пожалуйста, используйте другое название.'
                )

        return name

    def clean(self):
        """Дополнительная валидация: если выбран тип корректировки, указано значение"""
        cleaned_data = super().clean()

        adjustment_type = cleaned_data.get('price_adjustment_type')
        adjustment_value = cleaned_data.get('price_adjustment_value')

        # Если выбран тип корректировки (не 'none'), значение обязательно
        if adjustment_type and adjustment_type != 'none':
            if not adjustment_value or adjustment_value == 0:
                raise forms.ValidationError(
                    'Укажите значение корректировки цены (> 0)'
                )

        return cleaned_data


class KitItemForm(forms.ModelForm):
    """
    Форма для одного компонента комплекта.
    Валидирует, что указан либо product, либо variant_group (но не оба).
    Если обе поля пусты - это пустая форма, которая будет удалена.
    """
    class Meta:
        model = KitItem
        fields = ['product', 'variant_group', 'sales_unit', 'quantity']
        labels = {
            'product': 'Конкретный товар',
            'variant_group': 'Группа вариантов',
            'sales_unit': 'Единица продажи',
            'quantity': 'Количество'
        }
        widgets = {
            'product': forms.Select(attrs={'class': 'form-control'}),
            'variant_group': forms.Select(attrs={'class': 'form-control'}),
            'sales_unit': forms.Select(attrs={'class': 'form-control'}),
            'quantity': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.001', 'min': '0'}),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Устанавливаем значение по умолчанию для quantity = 1
        if not self.instance.pk:  # Только для новых форм (создание, не редактирование)
            self.fields['quantity'].initial = 1

    def clean(self):
        cleaned_data = super().clean()
        product = cleaned_data.get('product')
        variant_group = cleaned_data.get('variant_group')
        sales_unit = cleaned_data.get('sales_unit')
        quantity = cleaned_data.get('quantity')

        # Подсчитываем, сколько полей заполнено
        filled_fields = sum([bool(product), bool(variant_group), bool(sales_unit)])

        # Если все поля пусты - это пустая форма (не валидируем, она будет удалена)
        if filled_fields == 0:
            # Для пустых форм обнуляем количество
            cleaned_data['quantity'] = None
            return cleaned_data

        # Валидация несовместимых полей
        if variant_group and (product or sales_unit):
            raise forms.ValidationError(
                "Нельзя указывать группу вариантов одновременно с товаром или единицей продажи."
            )
        
        # Если выбрана единица продажи, товар обязателен
        if sales_unit and not product:
            raise forms.ValidationError("Для единицы продажи должен быть выбран товар.")

        # Валидация: если выбран товар/группа/единица продажи, количество обязательно и должно быть > 0
        if not quantity or quantity <= 0:
            raise forms.ValidationError('Необходимо указать количество больше 0')

        # Валидация: если выбрана единица продажи, проверяем, что она принадлежит выбранному продукту
        if sales_unit and product and sales_unit.product != product:
            raise forms.ValidationError('Выбранная единица продажи не принадлежит указанному товару.')

        return cleaned_data


# Кастомный базовый формсет с валидацией на дубликаты
class BaseKitItemFormSet(forms.BaseInlineFormSet):
    def clean(self):
        """Проверка на дубликаты товаров в комплекте"""
        if any(self.errors):
            # Не проверяем дубликаты если есть другие ошибки
            return

        products = []
        variant_groups = []
        sales_units = []

        for form in self.forms:
            if self.can_delete and self._should_delete_form(form):
                continue

            product = form.cleaned_data.get('product')
            variant_group = form.cleaned_data.get('variant_group')
            sales_unit = form.cleaned_data.get('sales_unit')

            # Проверка дубликатов товаров
            if product:
                if product in products:
                    raise forms.ValidationError(
                        f'Товар "{product.name}" добавлен в комплект более одного раза. '
                        f'Каждый товар может быть добавлен только один раз.'
                    )
                products.append(product)

            # Проверка дубликатов групп вариантов
            if variant_group:
                if variant_group in variant_groups:
                    raise forms.ValidationError(
                        f'Группа вариантов "{variant_group.name}" добавлена более одного раза. '
                        f'Каждая группа может быть добавлена только один раз.'
                    )
                variant_groups.append(variant_group)

            # Проверка дубликатов единиц продажи
            if sales_unit:
                if sales_unit in sales_units:
                    raise forms.ValidationError(
                        f'Единица продажи "{sales_unit.name}" добавлена в комплект более одного раза. '
                        f'Каждая единица продажи может быть добавлена только один раз.'
                    )
                sales_units.append(sales_unit)

# Формсет для создания комплектов (с пустой формой для удобства)
KitItemFormSetCreate = inlineformset_factory(
    ProductKit,
    KitItem,
    form=KitItemForm,
    formset=BaseKitItemFormSet,
    fields=['product', 'variant_group', 'sales_unit', 'quantity'],
    extra=1,  # Показать 1 пустую форму для первого компонента
    can_delete=True,  # Разрешить удаление компонентов
    min_num=0,  # Минимум 0 компонентов (можно создать пустой комплект)
    validate_min=False,  # Не требовать минимум компонентов
    can_delete_extra=True,  # Разрешить удалять дополнительные формы
)

# Формсет для редактирования комплектов (без пустых форм, только существующие компоненты)
KitItemFormSetUpdate = inlineformset_factory(
    ProductKit,
    KitItem,
    form=KitItemForm,
    formset=BaseKitItemFormSet,
    fields=['product', 'variant_group', 'sales_unit', 'quantity'],
    extra=0,  # НЕ показывать пустые формы при редактировании
    can_delete=True,  # Разрешить удаление компонентов
    min_num=0,  # Минимум 0 компонентов
    validate_min=False,  # Не требовать минимум компонентов
    can_delete_extra=True,  # Разрешить удалять дополнительные формы
)

# Для обратной совместимости (если где-то еще используется KitItemFormSet)
KitItemFormSet = KitItemFormSetCreate


class ProductCategoryForm(SKUUniqueMixin, forms.ModelForm):
    """
    Форма для создания и редактирования категории товаров.
    Поле photos НЕ включено в форму - файлы обрабатываются отдельно в view.
    """
    parent = forms.ModelChoiceField(
        queryset=ProductCategory.objects.filter(is_active=True),
        required=False,
        empty_label="Нет (корневая категория)",
        label="Родительская категория",
        widget=forms.Select(attrs={'class': 'form-control'})
    )

    class Meta:
        model = ProductCategory
        fields = ['name', 'sku', 'slug', 'parent', 'is_active']
        labels = {
            'name': 'Название',
            'sku': 'Артикул',
            'slug': 'URL-идентификатор',
            'parent': 'Родительская категория',
            'is_active': 'Активна'
        }
        help_texts = {
            'sku': 'Оставьте пустым для автоматической генерации (CAT-XXXX)',
            'slug': 'Оставьте пустым для автоматической генерации из названия',
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Make fields more user-friendly
        self.fields['name'].widget.attrs.update({
            'class': 'form-control form-control-lg fw-semibold',
            'placeholder': 'Введите название категории'
        })
        self.fields['sku'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'CAT-XXXX (автоматически)'
        })
        self.fields['slug'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'url-identifier (автоматически)'
        })
        self.fields['slug'].required = False  # Делаем поле необязательным
        self.fields['is_active'].widget.attrs.update({'class': 'form-check-input'})

        # Исключаем текущую категорию и её потомков из списка родительских
        # (чтобы не создать циклическую зависимость)
        if self.instance and self.instance.pk:
            # Получаем все потомки текущей категории
            descendants = self._get_descendants(self.instance)
            # Исключаем текущую категорию и все её потомки
            exclude_ids = [self.instance.pk] + [cat.pk for cat in descendants]
            self.fields['parent'].queryset = ProductCategory.objects.filter(
                is_active=True
            ).exclude(pk__in=exclude_ids)

    def clean_name(self):
        """Валидация уникальности имени для активных категорий"""
        name = self.cleaned_data.get('name')

        if name:
            # Проверяем уникальность имени среди активных категорий
            existing = ProductCategory.objects.filter(
                name=name,
                is_deleted=False
            )

            if self.instance.pk:
                existing = existing.exclude(pk=self.instance.pk)

            if existing.exists():
                raise forms.ValidationError(
                    f'Категория с названием "{name}" уже существует. '
                    f'Пожалуйста, используйте другое название.'
                )

        return name

    def clean_slug(self):
        """Преобразуем пустую строку в None для автогенерации slug"""
        slug = self.cleaned_data.get('slug')
        if slug == '' or slug is None:
            return None
        return slug

    def _get_descendants(self, category):
        """Рекурсивно получает всех потомков категории"""
        descendants = []
        children = category.children.all()
        for child in children:
            descendants.append(child)
            descendants.extend(self._get_descendants(child))
        return descendants


# ==================== VARIANT GROUP FORMS ====================

class ProductVariantGroupForm(forms.ModelForm):
    """
    Форма для создания и редактирования группы вариантов товара.
    """
    class Meta:
        model = ProductVariantGroup
        fields = ['name', 'description']
        labels = {
            'name': 'Название группы',
            'description': 'Описание (для какого букета или ситуации создана)'
        }
        widgets = {
            'name': forms.TextInput(attrs={
                'class': 'form-control form-control-lg fw-semibold',
                'placeholder': 'Например: Роза красная Freedom'
            }),
            'description': forms.Textarea(attrs={
                'class': 'form-control',
                'rows': 3,
                'placeholder': 'Описание группы и её использования'
            }),
        }


class ProductVariantGroupItemForm(forms.ModelForm):
    """
    Форма для добавления товара в группу с приоритетом.
    """
    class Meta:
        model = ProductVariantGroupItem
        fields = ['product', 'priority']
        labels = {
            'product': 'Товар',
            'priority': 'Приоритет'
        }
        widgets = {
            'product': forms.Select(attrs={'class': 'form-control form-control-sm'}),
            'priority': forms.NumberInput(attrs={
                'class': 'form-control form-control-sm',
                'min': '1',
                'placeholder': '1, 2, 3...'
            }),
        }


# Базовый формсет с валидацией на дубликаты
class BaseProductVariantGroupItemFormSet(forms.BaseInlineFormSet):
    def clean(self):
        """Проверка на дубликаты товаров в группе"""
        if any(self.errors):
            return

        products = []

        for form in self.forms:
            if self.can_delete and self._should_delete_form(form):
                continue

            product = form.cleaned_data.get('product')

            # Проверка дубликатов товаров
            if product:
                if product in products:
                    raise forms.ValidationError(
                        f'Товар "{product.name}" уже добавлен в группу. '
                        f'Каждый товар может быть добавлен только один раз.'
                    )
                products.append(product)


# Формсет для создания групп (с пустой формой для добавления товара)
ProductVariantGroupItemFormSetCreate = inlineformset_factory(
    ProductVariantGroup,
    ProductVariantGroupItem,
    form=ProductVariantGroupItemForm,
    formset=BaseProductVariantGroupItemFormSet,
    fields=['product', 'priority'],
    extra=1,  # Показать 1 пустую форму для первого товара
    can_delete=True,  # Разрешить удаление товаров
    min_num=0,  # Минимум 0 товаров (можно создать пустую группу)
    validate_min=False,  # Не требовать минимум товаров
    can_delete_extra=True,  # Разрешить удалять дополнительные формы
)

# Формсет для редактирования групп (без пустых форм, только существующие товары)
ProductVariantGroupItemFormSetUpdate = inlineformset_factory(
    ProductVariantGroup,
    ProductVariantGroupItem,
    form=ProductVariantGroupItemForm,
    formset=BaseProductVariantGroupItemFormSet,
    fields=['product', 'priority'],
    extra=0,  # НЕ показывать пустые формы при редактировании
    can_delete=True,  # Разрешить удаление товаров
    min_num=0,  # Минимум 0 товаров
    validate_min=False,  # Не требовать минимум товаров
    can_delete_extra=True,  # Разрешить удалять дополнительные формы
)


class ProductTagForm(forms.ModelForm):
    """
    Форма для создания и редактирования тегов товаров.
    """
    class Meta:
        model = ProductTag
        fields = ['name', 'slug', 'is_active']
        labels = {
            'name': 'Название',
            'slug': 'URL-идентификатор',
            'is_active': 'Активен'
        }
        help_texts = {
            'slug': 'Оставьте пустым для автоматической генерации из названия',
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['name'].widget.attrs.update({
            'class': 'form-control form-control-lg fw-semibold',
            'placeholder': 'Введите название тега'
        })
        self.fields['slug'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'url-identifier (автоматически)'
        })
        self.fields['slug'].required = False
        self.fields['is_active'].widget.attrs.update({'class': 'form-check-input'})

    def clean(self):
        """Валидация уникальности имени для активных тегов"""
        cleaned_data = super().clean()
        name = cleaned_data.get('name')
        is_active = cleaned_data.get('is_active', True)

        if name and is_active:
            # Проверяем уникальность имени среди активных тегов
            existing = ProductTag.objects.filter(
                name=name,
                is_active=True
            )

            if self.instance.pk:
                existing = existing.exclude(pk=self.instance.pk)

            if existing.exists():
                self.add_error('name',
                    f'Тег с названием "{name}" уже существует. '
                    f'Пожалуйста, используйте другое название.'
                )

        return cleaned_data

    def clean_slug(self):
        """Разрешаем пустой slug - он сгенерируется в модели"""
        slug = self.cleaned_data.get('slug')
        if slug == '' or slug is None:
            return None
        return slug


# ==================== CONFIGURABLE KIT FORMS ====================

class ConfigurableProductForm(SKUUniqueMixin, forms.ModelForm):
    """
    Форма для создания и редактирования вариативного товара.
    """
    external_category = forms.ModelChoiceField(
        queryset=ProductCategory.objects.filter(is_active=True),
        required=False,
        empty_label="Не выбрана",
        label="Внешняя категория",
        help_text="Категория для интеграций с внешними площадками (Recommerce, WooCommerce и др.)",
        widget=forms.Select(attrs={'class': 'form-select'})
    )

    class Meta:
        model = ConfigurableProduct
        fields = ['name', 'sku', 'description', 'short_description', 'external_category', 'status']
        labels = {
            'name': 'Название',
            'sku': 'Артикул',
            'description': 'Полное описание',
            'short_description': 'Краткое описание',
            'status': 'Статус'
        }
        help_texts = {
            'sku': 'Оставьте пустым для автогенерации в формате VAR-XXXXXX',
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['name'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Введите название вариативного товара'
        })
        self.fields['sku'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'VAR-XXXXXX (автогенерация)'
        })
        self.fields['sku'].required = False
        self.fields['description'].widget.attrs.update({
            'class': 'form-control',
            'rows': 5
        })
        self.fields['short_description'].widget.attrs.update({
            'class': 'form-control',
            'rows': 3,
            'placeholder': 'Краткое описание для экспорта'
        })
        self.fields['status'].widget.attrs.update({'class': 'form-select'})


class ConfigurableProductOptionForm(forms.ModelForm):
    """
    Форма для добавления варианта (комплекта) к вариативному товару.
    Атрибуты варианта выбираются динамически на основе parent_attributes.
    """
    kit = forms.ModelChoiceField(
        queryset=ProductKit.objects.filter(status='active', is_temporary=False).order_by('name'),
        required=True,
        label="Комплект",
        widget=forms.Select(attrs={'class': 'form-select'})
    )

    class Meta:
        model = ConfigurableProductOption
        # Убрали 'attributes' - он будет заполняться через ConfigurableProductOptionAttribute
        fields = ['kit', 'is_default']
        labels = {
            'kit': 'Комплект',
            'is_default': 'По умолчанию'
        }
        widgets = {
            'is_default': forms.CheckboxInput(attrs={
                'class': 'form-check-input is-default-switch',
                'role': 'switch'
            })
        }

    def __init__(self, *args, **kwargs):
        """
        Динамически генерируем поля для выбора атрибутов на основе parent_attributes.
        """
        super().__init__(*args, **kwargs)

        # Получаем instance (ConfigurableProductOption)
        if self.instance and self.instance.parent_id:
            parent = self.instance.parent
            # Получаем все уникальные названия атрибутов родителя
            attributes = parent.parent_attributes.all().order_by('position', 'name').distinct('name')

            # Создаем поле для каждого названия атрибута
            for attr in attributes:
                attr_name = attr.name
                field_name = f'attribute_{attr_name}'

                # Получаем все возможные значения для этого атрибута
                options = parent.parent_attributes.filter(name=attr_name).values_list('id', 'option')

                # Создаем ChoiceField для выбора значения
                self.fields[field_name] = forms.ModelChoiceField(
                    queryset=parent.parent_attributes.filter(name=attr_name),
                    required=True,
                    label=attr_name,
                    widget=forms.Select(attrs={'class': 'form-select', 'data-attribute-name': attr_name}),
                    to_field_name='id'
                )

                # Если редактируем существующий вариант - устанавливаем текущее значение
                if self.instance.pk:
                    current_attr = self.instance.attributes_set.filter(attribute__name=attr_name).first()
                    if current_attr:
                        self.fields[field_name].initial = current_attr.attribute


class BaseConfigurableProductOptionFormSet(forms.BaseInlineFormSet):
    def clean(self):
        """Проверка на дубликаты комплектов и что все атрибуты заполнены"""
        if any(self.errors):
            return

        kits = []
        default_count = 0

        for idx, form in enumerate(self.forms):
            if self.can_delete and self._should_delete_form(form):
                continue

            # Пропускаем пустые формы (extra формы при создании)
            if not form.cleaned_data or not form.cleaned_data.get('kit'):
                continue

            kit = form.cleaned_data.get('kit')
            is_default = form.cleaned_data.get('is_default')

            # Проверка дубликатов комплектов
            if kit:
                if kit in kits:
                    raise forms.ValidationError(
                        f'Комплект "{kit.name}" добавлен более одного раза. '
                        f'Каждый комплект может быть добавлен только один раз.'
                    )
                kits.append(kit)

            # Считаем количество "is_default"
            if is_default:
                default_count += 1

            # Проверяем что все атрибуты заполнены для варианта с kit
            parent = self.instance
            if parent and parent.pk:
                # Получаем все уникальные названия атрибутов родителя
                attribute_names = list(
                    parent.parent_attributes
                    .all()
                    .order_by('position', 'name')
                    .distinct('name')
                    .values_list('name', flat=True)
                )

                # Если у товара есть параметры, вариант ОБЯЗАН иметь значения для них
                if attribute_names:
                    # Проверяем что каждый атрибут выбран
                    missing_attributes = []
                    for attr_name in attribute_names:
                        field_name = f'attribute_{attr_name}'
                        if field_name not in form.cleaned_data or not form.cleaned_data[field_name]:
                            missing_attributes.append(attr_name)

                    if missing_attributes:
                        attrs_str = ', '.join(f'"{attr}"' for attr in missing_attributes)
                        raise forms.ValidationError(
                            f'Вариант {idx + 1}: необходимо заполнить атрибут(ы) {attrs_str}.'
                        )
                else:
                    # Если у товара нет параметров, вариант без привязки к параметрам бессмысленен
                    raise forms.ValidationError(
                        f'Вариант {idx + 1}: сначала добавьте параметры товара в разделе "Параметры товара".'
                    )

        # Проверяем, что не более одного "is_default"
        if default_count > 1:
            raise forms.ValidationError(
                'Можно установить только один вариант как "по умолчанию".'
            )


# Формсет для создания вариативного товара
ConfigurableProductOptionFormSetCreate = inlineformset_factory(
    ConfigurableProduct,
    ConfigurableProductOption,
    form=ConfigurableProductOptionForm,
    formset=BaseConfigurableProductOptionFormSet,
    fields=['kit', 'is_default'],  # Убрали 'attributes' - заполняется через ConfigurableProductOptionAttribute
    extra=0,  # Не требуем пустые формы (варианты скрыты в UI)
    can_delete=True,
    min_num=0,
    validate_min=False,
    can_delete_extra=True,
)

# Формсет для редактирования вариативного товара
ConfigurableProductOptionFormSetUpdate = inlineformset_factory(
    ConfigurableProduct,
    ConfigurableProductOption,
    form=ConfigurableProductOptionForm,
    formset=BaseConfigurableProductOptionFormSet,
    fields=['kit', 'is_default'],  # Убрали 'attributes' - заполняется через ConfigurableProductOptionAttribute
    extra=0,  # НЕ показывать пустые формы
    can_delete=True,
    min_num=0,
    validate_min=False,
    can_delete_extra=True,
)


# === Формы для атрибутов родительского вариативного товара ===

class ConfigurableProductAttributeForm(forms.ModelForm):
    """
    Форма для добавления атрибута родительского товара в карточном интерфейсе.
    На фронтенде: одна карточка параметра (имя + позиция + видимость)
    + множество инлайн значений через JavaScript

    Пример структуры:
    - name: "Длина"
    - position: 0
    - visible: True
    - values: [50, 60, 70] (будут созданы как отдельные ConfigurableProductAttribute)
    """
    class Meta:
        model = ConfigurableProductAttribute
        fields = ['name', 'position', 'visible']
        labels = {
            'name': 'Название параметра',
            'position': 'Порядок',
            'visible': 'Видимый на витрине'
        }
        widgets = {
            'name': forms.TextInput(attrs={
                'class': 'form-control param-name-input',
                'placeholder': 'Например: Длина, Цвет, Размер'
            }),
            'position': forms.NumberInput(attrs={
                'class': 'form-control param-position-input',
                'min': '0',
                'value': '0'
            }),
            'visible': forms.CheckboxInput(attrs={
                'class': 'form-check-input param-visible-input'
            })
        }


class BaseConfigurableProductAttributeFormSet(forms.BaseInlineFormSet):
    def clean(self):
        """Проверка на дубликаты параметров и что у каждого параметра есть значения"""
        if any(self.errors):
            return

        parameter_names = []

        for form in self.forms:
            if self.can_delete and self._should_delete_form(form):
                continue

            # Пропускаем пустые формы
            if not form.cleaned_data.get('name'):
                continue

            name = form.cleaned_data.get('name').strip()

            # Проверка дубликатов параметров (в карточном интерфейсе каждый параметр должен быть один раз)
            if name in parameter_names:
                raise forms.ValidationError(
                    f'Параметр "{name}" добавлен более одного раза. '
                    f'Каждый параметр должен быть добавлен только один раз.'
                )
            parameter_names.append(name)


# Формсет для создания атрибутов родительского товара (карточный интерфейс)
ConfigurableProductAttributeFormSetCreate = inlineformset_factory(
    ConfigurableProduct,
    ConfigurableProductAttribute,
    form=ConfigurableProductAttributeForm,
    formset=BaseConfigurableProductAttributeFormSet,
    # Убрали 'option' - значения будут добавляться через JavaScript в карточку
    fields=['name', 'position', 'visible'],
    extra=0,  # Пользователь добавляет параметры через кнопку "Добавить параметр"
    can_delete=True,
    min_num=0,
    validate_min=False,
    can_delete_extra=True,
)

# Формсет для редактирования атрибутов родительского товара
ConfigurableProductAttributeFormSetUpdate = inlineformset_factory(
    ConfigurableProduct,
    ConfigurableProductAttribute,
    form=ConfigurableProductAttributeForm,
    formset=BaseConfigurableProductAttributeFormSet,
    # Убрали 'option' - значения будут добавляться через JavaScript в карточку
    fields=['name', 'position', 'visible'],
    extra=0,
    can_delete=True,
    min_num=0,
    validate_min=False,
    can_delete_extra=True,
)


# ==========================================
# Формы для справочника атрибутов
# ==========================================

class ProductAttributeForm(forms.ModelForm):
    """Форма для создания и редактирования атрибута"""

    class Meta:
        model = ProductAttribute
        fields = ['name', 'slug', 'description', 'position']
        labels = {
            'name': 'Название',
            'slug': 'Slug (URL)',
            'description': 'Описание',
            'position': 'Позиция'
        }
        help_texts = {
            'slug': 'Оставьте пустым для автогенерации'
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['name'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Например: Длина стебля'
        })
        self.fields['slug'].widget.attrs.update({
            'class': 'form-control',
            'placeholder': 'Автоматически'
        })
        self.fields['slug'].required = False
        self.fields['description'].widget.attrs.update({
            'class': 'form-control',
            'rows': 2,
            'placeholder': 'Опциональное описание'
        })
        self.fields['position'].widget.attrs.update({
            'class': 'form-control',
            'style': 'width: 100px;'
        })


class ProductAttributeValueForm(forms.ModelForm):
    """Форма для значения атрибута (inline)"""

    class Meta:
        model = ProductAttributeValue
        fields = ['value', 'slug', 'position']
        labels = {
            'value': 'Значение',
            'slug': 'Slug',
            'position': 'Позиция'
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['value'].widget.attrs.update({
            'class': 'form-control form-control-sm',
            'placeholder': 'Например: 50'
        })
        self.fields['slug'].widget.attrs.update({
            'class': 'form-control form-control-sm',
            'placeholder': 'Авто'
        })
        self.fields['slug'].required = False
        self.fields['position'].widget.attrs.update({
            'class': 'form-control form-control-sm',
            'style': 'width: 70px;'
        })


ProductAttributeValueFormSet = inlineformset_factory(
    ProductAttribute,
    ProductAttributeValue,
    form=ProductAttributeValueForm,
    fields=['value', 'slug', 'position'],
    extra=3,
    can_delete=True,
    min_num=0,
    validate_min=False,
)


class ProductSalesUnitForm(forms.ModelForm):
    """
    Форма для создания и редактирования единицы продажи товара
    """
    class Meta:
        model = ProductSalesUnit
        fields = [
            'product', 'name', 'conversion_factor',
            'price', 'sale_price', 'min_quantity', 'quantity_step',
            'is_default', 'is_active', 'position'
        ]
        labels = {
            'product': 'Товар',
            'name': 'Название',
            'conversion_factor': 'Коэффициент конверсии',
            'price': 'Цена продажи',
            'sale_price': 'Цена со скидкой',
            'min_quantity': 'Минимальное количество',
            'quantity_step': 'Шаг количества',
            'is_default': 'По умолчанию',
            'is_active': 'Активна',
            'position': 'Порядок сортировки'
        }
        widgets = {
            'product': forms.Select(attrs={'class': 'form-control'}),
            'name': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Например: Ветка большая, Стебель средний'
            }),
            'conversion_factor': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.000001',
                'min': '0.000001',
                'placeholder': '15.0'
            }),
            'price': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.01',
                'min': '0',
                'placeholder': '0.00'
            }),
            'sale_price': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.01',
                'min': '0',
                'placeholder': 'Оставьте пустым если нет скидки'
            }),
            'min_quantity': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.001',
                'min': '0.001',
                'value': '1'
            }),
            'quantity_step': forms.NumberInput(attrs={
                'class': 'form-control',
                'step': '0.001',
                'min': '0.001',
                'value': '1'
            }),
            'is_default': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
            'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
            'position': forms.NumberInput(attrs={'class': 'form-control', 'value': '0'}),
        }
        help_texts = {
            'conversion_factor': 'Сколько единиц продажи получается из 1 базовой единицы товара. Например: 15 (из 1 банча получается 15 больших веток)',
            'price': 'Цена за одну единицу продажи',
            'sale_price': 'Опционально: цена со скидкой (должна быть меньше основной)',
            'min_quantity': 'Минимальное количество для заказа',
            'quantity_step': 'С каким шагом можно заказывать (например: 0.5, 1)',
            'is_default': 'Эта единица будет выбрана по умолчанию при добавлении товара в заказ',
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Фильтруем только активные товары
        self.fields['product'].queryset = Product.objects.filter(
            status='active'
        ).order_by('name')

        # Сделать sale_price необязательным
        self.fields['sale_price'].required = False


class UnitOfMeasureForm(forms.ModelForm):
    """
    Форма для создания и редактирования единицы измерения
    """
    class Meta:
        model = UnitOfMeasure
        fields = ['code', 'name', 'short_name', 'position', 'is_active']
        labels = {
            'code': 'Код',
            'name': 'Название',
            'short_name': 'Сокращение',
            'position': 'Порядок сортировки',
            'is_active': 'Активна',
        }
        widgets = {
            'code': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'шт, кг, банч'
            }),
            'name': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'Штука, Килограмм, Банч'
            }),
            'short_name': forms.TextInput(attrs={
                'class': 'form-control',
                'placeholder': 'шт., кг., бан.'
            }),
            'position': forms.NumberInput(attrs={
                'class': 'form-control',
                'value': '0'
            }),
            'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
        }
        help_texts = {
            'code': 'Короткий уникальный код (используется в системе)',
            'name': 'Полное название для отображения',
            'short_name': 'Сокращённое название для таблиц',
            'position': 'Порядок в списках (меньше = выше)',
        }


# === INLINE FORMSET ДЛЯ ЕДИНИЦ ПРОДАЖИ ===

class ProductSalesUnitInlineForm(forms.ModelForm):
    """
    Форма единицы продажи для inline редактирования в форме товара
    """
    class Meta:
        model = ProductSalesUnit
        fields = [
            'name', 'conversion_factor',
            'price', 'sale_price', 'min_quantity', 'quantity_step',
            'is_default', 'is_active', 'position'
        ]
        widgets = {
            'name': forms.TextInput(attrs={
                'class': 'form-control form-control-sm',
                'placeholder': 'Ветка большая'
            }),
            'conversion_factor': forms.NumberInput(attrs={
                'class': 'form-control form-control-sm',
                'step': '0.000001',
                'min': '0.000001',
                'placeholder': '15.0'
            }),
            'price': forms.NumberInput(attrs={
                'class': 'form-control form-control-sm',
                'step': '0.01',
                'min': '0',
            }),
            'sale_price': forms.NumberInput(attrs={
                'class': 'form-control form-control-sm',
                'step': '0.01',
                'min': '0',
            }),
            'min_quantity': forms.NumberInput(attrs={
                'class': 'form-control form-control-sm',
                'step': '0.001',
                'min': '0.001',
                'value': '1'
            }),
            'quantity_step': forms.NumberInput(attrs={
                'class': 'form-control form-control-sm',
                'step': '0.001',
                'min': '0.001',
                'value': '1'
            }),
            'is_default': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
            'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
            'position': forms.NumberInput(attrs={
                'class': 'form-control form-control-sm',
                'style': 'width: 60px;'
            }),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['sale_price'].required = False

    def has_changed(self):
        """
        Считаем форму неизмененной, если это новая форма без заполненных полей.
        Это позволяет избежать ошибок валидации для пустых добавленных форм.
        """
        # Если это существующая запись - используем стандартную логику
        if self.instance.pk:
            return super().has_changed()

        # Для новых форм проверяем, есть ли заполненные данные
        try:
            # Проверяем ключевые поля
            cleaned_data = getattr(self, 'cleaned_data', {})
            if cleaned_data.get('name'):
                return True
            if cleaned_data.get('price'):
                return True

            # Если cleaned_data ещё нет, проверяем raw data
            data = self.data if hasattr(self, 'data') else {}
            prefix = self.prefix
            name_field = f'{prefix}-name'
            price_field = f'{prefix}-price'

            if data.get(name_field):
                return True
            if data.get(price_field):
                return True

            # Форма пустая - считаем неизмененной
            return False
        except Exception:
            # При ошибке используем стандартную логику
            return super().has_changed()


# Inline formset для единиц продажи
ProductSalesUnitFormSet = inlineformset_factory(
    Product,
    ProductSalesUnit,
    form=ProductSalesUnitInlineForm,
    extra=1,
    can_delete=True,
    min_num=0,
    validate_min=False,
)
