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

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 WriteOffDocument, WriteOffDocumentItem
from inventory.forms import WriteOffDocumentForm, WriteOffDocumentItemForm
from inventory.services.writeoff_document_service import WriteOffDocumentService


class WriteOffDocumentListView(LoginRequiredMixin, ListView):
    """Список документов списания"""
    model = WriteOffDocument
    template_name = 'inventory/writeoff_document/list.html'
    context_object_name = 'documents'
    paginate_by = 20

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


class WriteOffDocumentCreateView(LoginRequiredMixin, CreateView):
    """Создание документа списания"""
    model = WriteOffDocument
    form_class = WriteOffDocumentForm
    template_name = 'inventory/writeoff_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 = WriteOffDocumentService.create_document(
            warehouse=form.cleaned_data['warehouse'],
            date=form.cleaned_data['date'],
            notes=form.cleaned_data.get('notes'),
            created_by=self.request.user
        )
        messages.success(self.request, f'Документ {document.document_number} создан')
        return redirect('inventory:writeoff-document-detail', pk=document.pk)


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

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

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['item_form'] = WriteOffDocumentItemForm(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 WriteOffDocumentAddItemView(LoginRequiredMixin, View):
    """Добавление позиции в документ списания"""

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

        if form.is_valid():
            try:
                item = WriteOffDocumentService.add_item(
                    document=document,
                    product=form.cleaned_data['product'],
                    quantity=form.cleaned_data['quantity'],
                    reason=form.cleaned_data['reason'],
                    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:writeoff-document-detail', pk=pk)


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

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

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

            WriteOffDocumentService.update_item(
                item,
                quantity=quantity,
                reason=reason,
                notes=notes
            )

            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:writeoff-document-detail', pk=pk)


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

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

        try:
            product_name = item.product.name
            WriteOffDocumentService.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:writeoff-document-detail', pk=pk)


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

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

        try:
            result = WriteOffDocumentService.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:writeoff-document-detail', pk=pk)


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

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

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

        return redirect('inventory:writeoff-document-list')
