"""
Views для работы с документами поступления (IncomingDocument).
"""

from django.views.generic import ListView, CreateView, DetailView, View
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse
from django.shortcuts import get_object_or_404, redirect
from django.contrib import messages
from django.http import JsonResponse
from django.db import transaction
from django.core.exceptions import ValidationError

from inventory.models import IncomingDocument, IncomingDocumentItem
from inventory.forms import IncomingDocumentForm, IncomingDocumentItemForm
from inventory.services.incoming_document_service import IncomingDocumentService


class IncomingDocumentListView(LoginRequiredMixin, ListView):
    """Список документов поступления"""
    model = IncomingDocument
    template_name = 'inventory/incoming_document/incoming_document_list.html'
    context_object_name = 'documents'
    paginate_by = 20

    def get_queryset(self):
        return IncomingDocument.objects.select_related(
            'warehouse', 'created_by', 'confirmed_by'
        ).prefetch_related('items').order_by('-date', '-created_at')


class IncomingDocumentCreateView(LoginRequiredMixin, CreateView):
    """Создание документа поступления"""
    model = IncomingDocument
    form_class = IncomingDocumentForm
    template_name = 'inventory/incoming_document/incoming_document_form.html'

    def get_initial(self):
        """Устанавливаем начальные значения для формы"""
        initial = super().get_initial()
        from django.utils import timezone
        initial['date'] = timezone.now().date()
        return initial

    def form_valid(self, form):
        document = IncomingDocumentService.create_document(
            warehouse=form.cleaned_data['warehouse'],
            date=form.cleaned_data['date'],
            receipt_type=form.cleaned_data['receipt_type'],
            supplier_name=form.cleaned_data.get('supplier_name'),
            notes=form.cleaned_data.get('notes'),
            created_by=self.request.user
        )
        messages.success(self.request, f'Документ {document.document_number} создан')
        return redirect('inventory:incoming-detail', pk=document.pk)


class IncomingDocumentDetailView(LoginRequiredMixin, DetailView):
    """Детальный просмотр документа поступления"""
    model = IncomingDocument
    template_name = 'inventory/incoming_document/incoming_document_detail.html'
    context_object_name = 'document'

    def get_queryset(self):
        return IncomingDocument.objects.select_related(
            'warehouse', 'created_by', 'confirmed_by'
        ).prefetch_related('items__product')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['item_form'] = IncomingDocumentItemForm(document=self.object)
        
        # Добавляем категории и теги для компонента поиска товаров
        from products.models import ProductCategory, ProductTag
        context['categories'] = ProductCategory.objects.filter(is_active=True).order_by('name')
        context['tags'] = ProductTag.objects.filter(is_active=True).order_by('name')
        
        return context


class IncomingDocumentAddItemView(LoginRequiredMixin, View):
    """Добавление позиции в документ поступления"""

    @transaction.atomic
    def post(self, request, pk):
        document = get_object_or_404(IncomingDocument, pk=pk)
        form = IncomingDocumentItemForm(request.POST, document=document)

        if form.is_valid():
            try:
                item = IncomingDocumentService.add_item(
                    document=document,
                    product=form.cleaned_data['product'],
                    quantity=form.cleaned_data['quantity'],
                    cost_price=form.cleaned_data['cost_price'],
                    notes=form.cleaned_data.get('notes')
                )

                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({
                        'success': True,
                        'item_id': item.id,
                        'message': f'Добавлено: {item.product.name}'
                    })

                messages.success(request, f'Добавлено: {item.product.name}')

            except ValidationError as e:
                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return JsonResponse({'success': False, 'error': str(e)}, status=400)
                messages.error(request, str(e))
        else:
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                errors = '; '.join([f"{k}: {v[0]}" for k, v in form.errors.items()])
                return JsonResponse({'success': False, 'error': errors}, status=400)
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f'{field}: {error}')

        return redirect('inventory:incoming-detail', pk=pk)


class IncomingDocumentUpdateItemView(LoginRequiredMixin, View):
    """Обновление позиции документа поступления"""

    @transaction.atomic
    def post(self, request, pk, item_pk):
        document = get_object_or_404(IncomingDocument, pk=pk)
        item = get_object_or_404(IncomingDocumentItem, pk=item_pk, document=document)

        try:
            quantity = request.POST.get('quantity')
            cost_price = request.POST.get('cost_price')
            notes = request.POST.get('notes')

            IncomingDocumentService.update_item(
                item,
                quantity=quantity if quantity else None,
                cost_price=cost_price if cost_price else None,
                notes=notes if notes else None
            )

            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'success': True,
                    'message': f'Обновлено: {item.product.name}'
                })

            messages.success(request, f'Обновлено: {item.product.name}')

        except ValidationError as e:
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({'success': False, 'error': str(e)}, status=400)
            messages.error(request, str(e))

        return redirect('inventory:incoming-detail', pk=pk)


class IncomingDocumentRemoveItemView(LoginRequiredMixin, View):
    """Удаление позиции из документа поступления"""

    @transaction.atomic
    def post(self, request, pk, item_pk):
        document = get_object_or_404(IncomingDocument, pk=pk)
        item = get_object_or_404(IncomingDocumentItem, pk=item_pk, document=document)

        try:
            product_name = item.product.name
            IncomingDocumentService.remove_item(item)

            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({
                    'success': True,
                    'message': f'Удалено: {product_name}'
                })

            messages.success(request, f'Удалено: {product_name}')

        except ValidationError as e:
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({'success': False, 'error': str(e)}, status=400)
            messages.error(request, str(e))

        return redirect('inventory:incoming-detail', pk=pk)


class IncomingDocumentConfirmView(LoginRequiredMixin, View):
    """Проведение документа поступления"""

    @transaction.atomic
    def post(self, request, pk):
        document = get_object_or_404(IncomingDocument, pk=pk)

        try:
            result = IncomingDocumentService.confirm_document(
                document,
                confirmed_by=request.user
            )
            messages.success(
                request,
                f'Документ {document.document_number} проведён. '
                f'Оприходовано {result["total_quantity"]} шт на сумму {result["total_cost"]:.2f}'
            )
        except ValidationError as e:
            messages.error(request, str(e))

        return redirect('inventory:incoming-detail', pk=pk)


class IncomingDocumentCancelView(LoginRequiredMixin, View):
    """Отмена документа поступления"""

    @transaction.atomic
    def post(self, request, pk):
        document = get_object_or_404(IncomingDocument, pk=pk)

        try:
            IncomingDocumentService.cancel_document(document)
            messages.success(request, f'Документ {document.document_number} отменён')
        except ValidationError as e:
            messages.error(request, str(e))

        return redirect('inventory:incoming-list')

