"""
Views для работы с трансформациями товаров (Transformation).
"""

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 Transformation, TransformationInput, TransformationOutput
from inventory.forms import TransformationForm, TransformationInputForm, TransformationOutputForm
from inventory.services.transformation_service import TransformationService


class TransformationListView(LoginRequiredMixin, ListView):
    """Список трансформаций товаров"""
    model = Transformation
    template_name = 'inventory/transformation/list.html'
    context_object_name = 'transformations'
    paginate_by = 20

    def get_queryset(self):
        return Transformation.objects.select_related(
            'warehouse', 'employee'
        ).prefetch_related('inputs__product', 'outputs__product').order_by('-date')


class TransformationCreateView(LoginRequiredMixin, CreateView):
    """Создание трансформации"""
    model = Transformation
    form_class = TransformationForm
    template_name = 'inventory/transformation/form.html'

    def form_valid(self, form):
        transformation = TransformationService.create_transformation(
            warehouse=form.cleaned_data['warehouse'],
            comment=form.cleaned_data.get('comment'),
            employee=self.request.user
        )
        messages.success(self.request, f'Трансформация {transformation.document_number} создана')
        return redirect('inventory:transformation-detail', pk=transformation.pk)


class TransformationDetailView(LoginRequiredMixin, DetailView):
    """Детальный просмотр трансформации"""
    model = Transformation
    template_name = 'inventory/transformation/detail.html'
    context_object_name = 'transformation'

    def get_queryset(self):
        return Transformation.objects.select_related(
            'warehouse', 'employee'
        ).prefetch_related('inputs__product', 'outputs__product')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['input_form'] = TransformationInputForm(transformation=self.object)
        context['output_form'] = TransformationOutputForm(transformation=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')
        
        # Вычисляем суммы для подсказки
        from decimal import Decimal
        total_input = sum(
            trans_input.quantity for trans_input in self.object.inputs.all()
        )
        total_output = sum(
            trans_output.quantity for trans_output in self.object.outputs.all()
        )
        context['total_input_quantity'] = total_input
        context['total_output_quantity'] = total_output
        context['quantity_balance'] = total_input - total_output

        return context


class TransformationAddInputView(LoginRequiredMixin, View):
    """Добавление входного товара в трансформацию"""

    @transaction.atomic
    def post(self, request, pk):
        transformation = get_object_or_404(Transformation, pk=pk)
        form = TransformationInputForm(request.POST, transformation=transformation)

        if form.is_valid():
            try:
                trans_input = TransformationService.add_input(
                    transformation=transformation,
                    product=form.cleaned_data['product'],
                    quantity=form.cleaned_data['quantity']
                )

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

                messages.success(request, f'Добавлено: {trans_input.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:transformation-detail', pk=pk)


class TransformationAddOutputView(LoginRequiredMixin, View):
    """Добавление выходного товара в трансформацию"""

    @transaction.atomic
    def post(self, request, pk):
        transformation = get_object_or_404(Transformation, pk=pk)
        form = TransformationOutputForm(request.POST, transformation=transformation)

        if form.is_valid():
            try:
                trans_output = TransformationService.add_output(
                    transformation=transformation,
                    product=form.cleaned_data['product'],
                    quantity=form.cleaned_data['quantity']
                )

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

                messages.success(request, f'Добавлено: {trans_output.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:transformation-detail', pk=pk)


class TransformationRemoveInputView(LoginRequiredMixin, View):
    """Удаление входного товара из трансформации"""

    @transaction.atomic
    def post(self, request, pk, item_pk):
        transformation = get_object_or_404(Transformation, pk=pk)
        trans_input = get_object_or_404(TransformationInput, pk=item_pk, transformation=transformation)

        try:
            product_name = trans_input.product.name
            TransformationService.remove_input(trans_input)

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


class TransformationRemoveOutputView(LoginRequiredMixin, View):
    """Удаление выходного товара из трансформации"""

    @transaction.atomic
    def post(self, request, pk, item_pk):
        transformation = get_object_or_404(Transformation, pk=pk)
        trans_output = get_object_or_404(TransformationOutput, pk=item_pk, transformation=transformation)

        try:
            product_name = trans_output.product.name
            TransformationService.remove_output(trans_output)

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


class TransformationConfirmView(LoginRequiredMixin, View):
    """Проведение трансформации"""

    @transaction.atomic
    def post(self, request, pk):
        transformation = get_object_or_404(Transformation, pk=pk)

        try:
            TransformationService.confirm(transformation)
            messages.success(request, f'Трансформация {transformation.document_number} проведена')
        except ValidationError as e:
            messages.error(request, str(e))

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


class TransformationCancelView(LoginRequiredMixin, View):
    """Отмена трансформации"""

    @transaction.atomic
    def post(self, request, pk):
        transformation = get_object_or_404(Transformation, pk=pk)

        try:
            TransformationService.cancel(transformation)
            messages.success(request, f'Трансформация {transformation.document_number} отменена')
        except ValidationError as e:
            messages.error(request, str(e))

        return redirect('inventory:transformation-list')
