"""
CRUD представления для справочника атрибутов товаров (ProductAttribute, ProductAttributeValue).
"""
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView, CreateView, DetailView, UpdateView, DeleteView
from django.urls import reverse_lazy
from django.db.models import Q, Count
from django.db import IntegrityError
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.contrib.auth.decorators import login_required
import json

from ..models import ProductAttribute, ProductAttributeValue
from ..forms import ProductAttributeForm, ProductAttributeValueFormSet


class ProductAttributeListView(LoginRequiredMixin, ListView):
    """Список всех атрибутов с поиском"""
    model = ProductAttribute
    template_name = 'products/attribute_list.html'
    context_object_name = 'attributes'
    paginate_by = 20

    def get_queryset(self):
        queryset = super().get_queryset()

        # Аннотируем количество значений для каждого атрибута
        queryset = queryset.annotate(
            num_values=Count('values', distinct=True)
        )

        # Поиск по названию и slug
        search_query = self.request.GET.get('search')
        if search_query:
            queryset = queryset.filter(
                Q(name__icontains=search_query) |
                Q(slug__icontains=search_query)
            )

        return queryset.order_by('position', 'name')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['search_query'] = self.request.GET.get('search', '')
        return context


class ProductAttributeDetailView(LoginRequiredMixin, DetailView):
    """Детальная информация об атрибуте с его значениями"""
    model = ProductAttribute
    template_name = 'products/attribute_detail.html'
    context_object_name = 'attribute'

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

        # Получаем все значения атрибута
        context['values'] = attribute.values.all().order_by('position', 'value')

        return context


class ProductAttributeCreateView(LoginRequiredMixin, CreateView):
    """Создание нового атрибута с inline значениями"""
    model = ProductAttribute
    form_class = ProductAttributeForm
    template_name = 'products/attribute_form.html'
    success_url = reverse_lazy('products:attribute-list')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.request.POST:
            context['value_formset'] = ProductAttributeValueFormSet(self.request.POST, instance=self.object)
        else:
            context['value_formset'] = ProductAttributeValueFormSet(instance=self.object)
        return context

    def form_valid(self, form):
        context = self.get_context_data()
        value_formset = context['value_formset']

        try:
            self.object = form.save()

            if value_formset.is_valid():
                value_formset.instance = self.object
                value_formset.save()
            else:
                return self.form_invalid(form)

            messages.success(self.request, f'Атрибут "{self.object.name}" успешно создан.')
            return super().form_valid(form)

        except IntegrityError as e:
            error_msg = str(e).lower()
            if 'unique' in error_msg:
                messages.error(
                    self.request,
                    f'Ошибка: атрибут с таким названием уже существует.'
                )
            else:
                messages.error(
                    self.request,
                    'Ошибка при сохранении атрибута. Пожалуйста, проверьте введённые данные.'
                )
            return self.form_invalid(form)


class ProductAttributeUpdateView(LoginRequiredMixin, UpdateView):
    """Редактирование существующего атрибута с inline значениями"""
    model = ProductAttribute
    form_class = ProductAttributeForm
    template_name = 'products/attribute_form.html'
    success_url = reverse_lazy('products:attribute-list')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.request.POST:
            context['value_formset'] = ProductAttributeValueFormSet(self.request.POST, instance=self.object)
        else:
            context['value_formset'] = ProductAttributeValueFormSet(instance=self.object)
        return context

    def form_valid(self, form):
        context = self.get_context_data()
        value_formset = context['value_formset']

        try:
            self.object = form.save()

            if value_formset.is_valid():
                value_formset.save()
            else:
                return self.form_invalid(form)

            messages.success(self.request, f'Атрибут "{self.object.name}" успешно обновлен.')
            return super().form_valid(form)

        except IntegrityError as e:
            error_msg = str(e).lower()
            if 'unique' in error_msg:
                messages.error(
                    self.request,
                    f'Ошибка: атрибут с таким названием уже существует.'
                )
            else:
                messages.error(
                    self.request,
                    'Ошибка при сохранении атрибута. Пожалуйста, проверьте введённые данные.'
                )
            return self.form_invalid(form)


class ProductAttributeDeleteView(LoginRequiredMixin, DeleteView):
    """Удаление атрибута с подтверждением"""
    model = ProductAttribute
    template_name = 'products/attribute_confirm_delete.html'
    success_url = reverse_lazy('products:attribute-list')

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

        # Количество значений
        context['values_count'] = attribute.values.count()

        return context

    def delete(self, request, *args, **kwargs):
        attribute = self.get_object()
        attribute_name = attribute.name
        response = super().delete(request, *args, **kwargs)
        messages.success(request, f'Атрибут "{attribute_name}" успешно удален.')
        return response


# API endpoints

@login_required
@require_POST
def create_attribute_api(request):
    """API для быстрого создания атрибута"""
    try:
        data = json.loads(request.body)
        name = data.get('name', '').strip()

        if not name:
            return JsonResponse({'success': False, 'error': 'Название обязательно'})

        attribute = ProductAttribute.objects.create(name=name)
        return JsonResponse({
            'success': True,
            'id': attribute.pk,
            'name': attribute.name,
            'slug': attribute.slug
        })
    except IntegrityError:
        return JsonResponse({'success': False, 'error': 'Атрибут с таким названием уже существует'})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})


@login_required
@require_POST
def add_attribute_value_api(request, pk):
    """API для добавления значения к атрибуту"""
    try:
        data = json.loads(request.body)
        value = data.get('value', '').strip()

        if not value:
            return JsonResponse({'success': False, 'error': 'Значение обязательно'})

        attribute = ProductAttribute.objects.get(pk=pk)
        attr_value = ProductAttributeValue.objects.create(
            attribute=attribute,
            value=value
        )
        return JsonResponse({
            'success': True,
            'id': attr_value.pk,
            'value': attr_value.value,
            'slug': attr_value.slug
        })
    except ProductAttribute.DoesNotExist:
        return JsonResponse({'success': False, 'error': 'Атрибут не найден'})
    except IntegrityError:
        return JsonResponse({'success': False, 'error': 'Такое значение уже существует'})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})


@login_required
@require_POST
def delete_attribute_value_api(request, pk, value_id):
    """API для удаления значения атрибута"""
    try:
        value = ProductAttributeValue.objects.get(pk=value_id, attribute_id=pk)
        value.delete()
        return JsonResponse({'success': True})
    except ProductAttributeValue.DoesNotExist:
        return JsonResponse({'success': False, 'error': 'Значение не найдено'})
    except Exception as e:
        return JsonResponse({'success': False, 'error': str(e)})


@login_required
def get_attributes_list_api(request):
    """
    API для получения списка всех атрибутов с их значениями.
    Используется для autocomplete в форме создания вариативного товара.
    """
    attributes = ProductAttribute.objects.prefetch_related('values').order_by('position', 'name')

    data = []
    for attr in attributes:
        data.append({
            'id': attr.pk,
            'name': attr.name,
            'slug': attr.slug,
            'values': [
                {
                    'id': val.pk,
                    'value': val.value,
                    'slug': val.slug
                }
                for val in attr.values.all().order_by('position', 'value')
            ]
        })

    return JsonResponse({'success': True, 'attributes': data})
