# -*- coding: utf-8 -*-
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from django.core.paginator import Paginator
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ValidationError
from django.db import models, transaction
from decimal import Decimal
from .models import Order, OrderItem, Address, OrderStatus, Transaction, PaymentMethod, Delivery
from .forms import OrderForm, OrderItemFormSet, OrderItemForm, OrderStatusForm, TransactionForm
from .filters import OrderFilter
from .services.address_service import AddressService
from inventory.models import Reservation
import json


from django.utils import timezone  # Added for default date filter

def order_list(request):
    """
    Список всех заказов с фильтрацией и поиском
    Использует django-filter для фильтрации данных
    """
    # Если параметров нет вообще (первый заход), редиректим на "Сегодня"
    if not request.GET:
        today = timezone.localdate().isoformat()
        return redirect(f'{request.path}?delivery_date_after={today}&delivery_date_before={today}')

    # Базовый queryset с оптимизацией запросов
    orders = Order.objects.select_related(
        'customer', 'delivery', 'delivery__address', 'delivery__pickup_warehouse', 'status'  # Добавлен 'status' для избежания N+1
    ).all()

    # Применяем фильтры через django-filter
    order_filter = OrderFilter(request.GET, queryset=orders)

    # Сортировка
    filtered_orders = order_filter.qs.order_by('-created_at')

    # Пагинация
    paginator = Paginator(filtered_orders, 25)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)

    context = {
        'filter': order_filter,
        'page_obj': page_obj,
        'status_choices': OrderStatus.objects.all().order_by('order'),
    }

    return render(request, 'orders/order_list.html', context)


def order_detail(request, order_number):
    """Детальная информация о заказе"""
    order = get_object_or_404(
        Order.objects.select_related('customer', 'delivery', 'delivery__address', 'delivery__pickup_warehouse', 'modified_by', 'status')
                     .prefetch_related('items__product', 'items__product_kit', 'transactions__created_by', 'transactions__payment_method'),
        order_number=order_number
    )

    context = {
        'order': order,
    }

    return render(request, 'orders/order_detail.html', context)


def order_create(request):
    """Создание нового заказа"""
    # Инициализация переменных для контекста
    preselected_customer = None
    draft_items = []
    
    if request.method == 'POST':

        
        form = OrderForm(request.POST)
        formset = OrderItemFormSet(request.POST)

        if form.is_valid() and formset.is_valid():
            try:
                with transaction.atomic():
                    # Сохраняем форму БЕЗ commit, чтобы не вызывать reset_delivery_cost() до сохранения items
                    order = form.save(commit=False)

                    # Обрабатываем получателя
                    recipient = AddressService.process_recipient_from_form(order, form.cleaned_data)
                    if recipient:
                        # Если получатель не существует в БД, сохраняем его
                        if not recipient.pk:
                            recipient.save()
                        order.recipient = recipient
                    else:
                        # Если покупатель является получателем
                        order.recipient = None

                    # Статус берём из формы (в том числе может быть "Черновик")
                    from accounts.models import CustomUser
                    if isinstance(request.user, CustomUser):
                        order.modified_by = request.user
                    else:
                        order.modified_by = None

                    # Сохраняем заказ в БД (теперь у него есть pk)
                    order.save()

                    # Сохраняем позиции заказа
                    formset.instance = order
                    formset.save()

                    # === Обработка витринных комплектов из POS ===
                    # Если заказ создан из POS с showcase_kit, обрабатываем ShowcaseItem
                    draft_token = request.GET.get('draft')
                    if draft_token:
                        from django.core.cache import cache
                        cache_key = f'pos_draft:{draft_token}'
                        draft_data = cache.get(cache_key)
                        
                        if draft_data and draft_data.get('items'):
                            from inventory.models import ShowcaseItem
                            from products.models import ProductKit
                            
                            # Проверяем статус заказа для выбора стратегии
                            is_final_positive = order.status and order.status.is_positive_end
                            
                            for draft_item in draft_data['items']:
                                if draft_item.get('type') == 'showcase_kit':
                                    showcase_item_ids = draft_item.get('showcase_item_ids', [])
                                    kit_id = draft_item.get('id')
                                    
                                    if not showcase_item_ids or not kit_id:
                                        continue
                                    
                                    # Находим соответствующий OrderItem
                                    kit = ProductKit.objects.get(id=kit_id)
                                    order_item = order.items.filter(
                                        product_kit=kit,
                                        is_from_showcase=True
                                    ).first()
                                    
                                    if not order_item:
                                        continue
                                    
                                    # Загружаем ShowcaseItem
                                    showcase_items = list(ShowcaseItem.objects.filter(
                                        id__in=showcase_item_ids
                                    ))
                                    
                                    if not showcase_items:
                                        continue
                                    
                                    # Выбираем стратегию в зависимости от статуса заказа
                                    if is_final_positive:
                                        # Прямая продажа (заказ сразу в completed - редкий случай)
                                        from inventory.services.showcase_manager import ShowcaseManager
                                        result = ShowcaseManager.sell_showcase_items(showcase_items, order_item)
                                        if not result['success']:
                                            raise ValidationError(result['message'])
                                    else:
                                        # Резервирование под отложенный заказ
                                        for showcase_item in showcase_items:
                                            showcase_item.reserve_for_order(order_item)

                    # Проверяем, является ли заказ черновиком
                    is_draft = order.status and order.status.code == 'draft'
                    
                    # ВАЖНО: Поля доставки НЕ включены в Meta.fields формы OrderForm,
                    # поэтому они не попадают в form.cleaned_data!
                    # Читаем их напрямую из request.POST и обрабатываем вручную
                    
                    # Получаем данные доставки из POST
                    delivery_type = request.POST.get('delivery_type', None)
                    
                    # Обрабатываем дату доставки
                    delivery_date_str = request.POST.get('delivery_date', None)
                    delivery_date = None
                    if delivery_date_str:
                        try:
                            from datetime import datetime
                            delivery_date = datetime.strptime(delivery_date_str, '%Y-%m-%d').date()
                        except (ValueError, TypeError):
                            pass
                    
                    # Обрабатываем время
                    time_from_str = request.POST.get('time_from', None)
                    time_from = None
                    if time_from_str:
                        try:
                            from datetime import datetime
                            time_from = datetime.strptime(time_from_str, '%H:%M').time()
                        except (ValueError, TypeError):
                            pass
                    
                    time_to_str = request.POST.get('time_to', None)
                    time_to = None
                    if time_to_str:
                        try:
                            from datetime import datetime
                            time_to = datetime.strptime(time_to_str, '%H:%M').time()
                        except (ValueError, TypeError):
                            pass
                    
                    # Обрабатываем стоимость доставки
                    delivery_cost_str = request.POST.get('delivery_cost', '0')
                    delivery_cost = Decimal('0')
                    if delivery_cost_str:
                        try:
                            delivery_cost = Decimal(delivery_cost_str.replace(',', '.'))
                        except (ValueError, TypeError):
                            pass
                            delivery_cost = Decimal('0')
                    
                    # Обрабатываем склад самовывоза
                    pickup_warehouse_id = request.POST.get('pickup_warehouse', None)
                    pickup_warehouse = None
                    if pickup_warehouse_id:
                        try:
                            from inventory.models import Warehouse
                            pickup_warehouse = Warehouse.objects.get(pk=pickup_warehouse_id)
                        except (Warehouse.DoesNotExist, ValueError):
                            pass
                    
                    # Обрабатываем адрес для курьерской доставки (даже для черновиков, если указан)
                    address = None
                    if delivery_type == Delivery.DELIVERY_TYPE_COURIER:
                        # Для курьерской доставки обрабатываем адрес, если он указан
                        address = AddressService.process_address_from_form(order, form.cleaned_data)
                        if address and not address.pk:
                            address.save()
                    
                    # Создаем или обновляем Delivery
                    # Ранее для не-черновиков адрес курьерской доставки был обязателен.
                    # Теперь разрешаем сохранять заказ в любом статусе без адреса.
                    if is_draft:
                        # Для черновиков создаем Delivery, если есть хотя бы адрес или данные доставки
                        if address or delivery_type or pickup_warehouse or delivery_date:
                            Delivery.objects.update_or_create(
                                order=order,
                                defaults={
                                    'delivery_type': delivery_type or Delivery.DELIVERY_TYPE_COURIER,
                                    'delivery_date': delivery_date,  # Может быть None для черновиков
                                    'time_from': time_from,
                                    'time_to': time_to,
                                    'address': address,
                                    'pickup_warehouse': pickup_warehouse,
                                    'cost': delivery_cost if delivery_cost else Decimal('0')
                                }
                            )
                    else:
                        # Для не-черновиков больше не требуем обязательного адреса.
                        # Если пользователь вообще не указал тип доставки и дату, просто не создаём Delivery.
                        if address or delivery_type or pickup_warehouse or delivery_date:
                            delivery = Delivery.objects.create(
                                order=order,
                                delivery_type=delivery_type or Delivery.DELIVERY_TYPE_COURIER,
                                delivery_date=delivery_date,
                                time_from=time_from,
                                time_to=time_to,
                                address=address,
                                pickup_warehouse=pickup_warehouse,
                                cost=delivery_cost if delivery_cost else Decimal('0')
                            )
                            
                            # Пересчитываем стоимость доставки если она не установлена вручную
                            if not delivery.cost or delivery.cost <= 0:
                                order.reset_delivery_cost()

                    # Пересчитываем итоговую стоимость
                    order.calculate_total()
                    order.update_payment_status()

                messages.success(request, f'Заказ #{order.order_number} успешно создан!')
                return redirect('orders:order-detail', order_number=order.order_number)
            except ValueError as e:
                # Ошибка в сигналах (например, не удалось создать Sale)
                # Транзакция откатилась, заказ НЕ создан
                messages.error(request, f'Ошибка при создании заказа: {e}')
        else:
            messages.error(request, 'Пожалуйста, исправьте ошибки в форме.')
    else:
        # Предзаполнение клиента из GET параметра
        initial_data = {}
        customer_id = request.GET.get('customer')
        
        # Проверяем, есть ли черновик из POS
        draft_token = request.GET.get('draft')
        if draft_token:
            from django.core.cache import cache
            cache_key = f'pos_draft:{draft_token}'
            draft_data = cache.get(cache_key)
            
            if draft_data:
                # Загружаем клиента из черновика
                customer_id = draft_data.get('customer_id')
                draft_items = draft_data.get('items', [])
                
                # Удаляем черновик из кэша (одноразовый токен)
                cache.delete(cache_key)
        
        if customer_id:
            try:
                from customers.models import Customer
                preselected_customer = Customer.objects.get(pk=customer_id)
                initial_data['customer'] = preselected_customer.pk
            except (Customer.DoesNotExist, ValueError):
                pass

        form = OrderForm(initial=initial_data)
        
        # Создаем formset с предзаполненными товарами из черновика
        if draft_items:
            from django.forms import inlineformset_factory
            from products.models import Product, ProductKit
            
            # Создаём формсет с нужным количеством extra форм
            DraftOrderItemFormSet = inlineformset_factory(
                Order,
                OrderItem,
                form=OrderItemForm,
                extra=len(draft_items),  # Создаём столько форм, сколько товаров
                can_delete=True,
                min_num=0,
                validate_min=False,
            )
            formset = DraftOrderItemFormSet()
        else:
            formset = OrderItemFormSet()

    context = {
        'form': form,
        'formset': formset,
        'preselected_customer': preselected_customer,
        'draft_items_json': json.dumps(draft_items) if draft_items else '[]',  # Передаём JSON товары из черновика
        'title': 'Создание заказа',
        'button_text': 'Создать заказ',
        'is_create_page': True,
    }

    return render(request, 'orders/order_form.html', context)


def order_update(request, order_number):
    """Редактирование заказа"""
    order = get_object_or_404(Order, order_number=order_number)
    
    # Пересчитываем amount_paid на основе транзакций (на случай миграции)
    order.recalculate_amount_paid()

    if request.method == 'POST':
        form = OrderForm(request.POST, instance=order)
        formset = OrderItemFormSet(request.POST, instance=order)





        if form.is_valid() and formset.is_valid():
            try:
                with transaction.atomic():
                    order = form.save(commit=False)

                    # Обрабатываем получателя
                    recipient = AddressService.process_recipient_from_form(order, form.cleaned_data)
                    if recipient:
                        # Сохраняем получателя: если новый - создаем, если существующий - обновляем
                        recipient.save()  # Django автоматически определит create или update
                        order.recipient = recipient
                        # Если покупатель является получателем
                        order.recipient = None

                    from accounts.models import CustomUser
                    if isinstance(request.user, CustomUser):
                        order.modified_by = request.user
                    else:
                         # Если это админ платформы, не перезаписываем поле (оставляем как есть)
                        pass

                    order.save()



                    formset.save()

                    # Проверяем, является ли заказ черновиком
                    is_draft = order.status and order.status.code == 'draft'

                    # ВАЖНО: Поля доставки НЕ включены в Meta.fields формы OrderForm,
                    # поэтому они не попадают в form.cleaned_data!
                    # Читаем их напрямую из request.POST и обрабатываем вручную
                    
                    # Получаем данные доставки из POST
                    delivery_type = request.POST.get('delivery_type', None)
                    
                    # Обрабатываем дату доставки
                    delivery_date_str = request.POST.get('delivery_date', None)
                    delivery_date = None
                    if delivery_date_str:
                        try:
                            from datetime import datetime
                            delivery_date = datetime.strptime(delivery_date_str, '%Y-%m-%d').date()
                        except (ValueError, TypeError):
                            pass
                    
                    # Обрабатываем время
                    time_from_str = request.POST.get('time_from', None)
                    time_from = None
                    if time_from_str:
                        try:
                            from datetime import datetime
                            time_from = datetime.strptime(time_from_str, '%H:%M').time()
                        except (ValueError, TypeError):
                            print(f"[DEBUG] Error parsing time_from: {time_from_str}")
                    
                    time_to_str = request.POST.get('time_to', None)
                    time_to = None
                    if time_to_str:
                        try:
                            from datetime import datetime
                            time_to = datetime.strptime(time_to_str, '%H:%M').time()
                        except (ValueError, TypeError):
                            pass
                    
                    # Обрабатываем стоимость доставки
                    delivery_cost_str = request.POST.get('delivery_cost', '0')
                    delivery_cost = Decimal('0')
                    if delivery_cost_str:
                        try:
                            delivery_cost = Decimal(delivery_cost_str.replace(',', '.'))
                        except (ValueError, TypeError):
                            pass
                            delivery_cost = Decimal('0')
                    
                    # Обрабатываем склад самовывоза
                    pickup_warehouse_id = request.POST.get('pickup_warehouse', None)
                    pickup_warehouse = None
                    if pickup_warehouse_id:
                        try:
                            from inventory.models import Warehouse
                            pickup_warehouse = Warehouse.objects.get(pk=pickup_warehouse_id)
                        except (Warehouse.DoesNotExist, ValueError):
                            pass




                    # Обрабатываем адрес для курьерской доставки (даже для черновиков, если указан)
                    address = None
                    if delivery_type == Delivery.DELIVERY_TYPE_COURIER:
                        # Для курьерской доставки обрабатываем адрес, если он указан
                        address = AddressService.process_address_from_form(order, form.cleaned_data)
                        if address and not address.pk:
                            address.save()

                    # Создаем или обновляем Delivery
                    # Ранее для не-черновиков адрес курьерской доставки был обязателен.
                    # Теперь разрешаем сохранять заказ в любом статусе без адреса.
                    if is_draft:
                        # Для черновиков создаем Delivery, если есть хотя бы адрес или данные доставки
                        if address or delivery_type or pickup_warehouse or delivery_date:
                            delivery_obj, created = Delivery.objects.update_or_create(
                                order=order,
                                defaults={
                                    'delivery_type': delivery_type or Delivery.DELIVERY_TYPE_COURIER,
                                    'delivery_date': delivery_date,  # Может быть None для черновиков
                                    'time_from': time_from,
                                    'time_to': time_to,
                                    'address': address,
                                    'pickup_warehouse': pickup_warehouse,
                                    'cost': delivery_cost if delivery_cost else Decimal('0')
                                }
                            )
                        elif hasattr(order, 'delivery'):
                            # Если все данные доставки очищены, удаляем существующую Delivery
                            order.delivery.delete()
                    else:
                        # Для не-черновиков больше не требуем обязательного адреса.
                        # Если пользователь вообще не указал данные доставки, удаляем Delivery (если она была).
                        if not (address or delivery_type or pickup_warehouse or delivery_date):
                            if hasattr(order, 'delivery'):
                                order.delivery.delete()
                        else:
                            # Создаем или обновляем Delivery с теми данными, что есть.
                            delivery, created = Delivery.objects.update_or_create(
                                order=order,
                                defaults={
                                    'delivery_type': delivery_type or Delivery.DELIVERY_TYPE_COURIER,
                                    'delivery_date': delivery_date,
                                    'time_from': time_from,
                                    'time_to': time_to,
                                    'address': address,
                                    'pickup_warehouse': pickup_warehouse,
                                    'cost': delivery_cost if delivery_cost else Decimal('0')
                                }
                            )
                    # Пересчитываем итоговую стоимость
                    order.calculate_total()
                    order.update_payment_status()

                messages.success(request, f'Заказ #{order.order_number} успешно обновлен!')
                return redirect('orders:order-detail', order_number=order.order_number)
            except ValidationError as e:
                # Ошибка валидации (например, запрет смены статуса для возвращённого заказа)
                # Транзакция откатилась, заказ НЕ изменился
                # Показываем сообщение из исключения без служебных элементов
                error_message = str(e.message) if hasattr(e, 'message') else str(e)
                # Если это список ошибок, берём первую
                if hasattr(e, 'messages'):
                    error_message = e.messages[0] if e.messages else str(e)
                messages.error(request, error_message)
            except ValueError as e:
                # Ошибка в сигналах (например, не удалось создать Sale)
                # Транзакция откатилась, статус НЕ изменился
                messages.error(request, f'Ошибка при сохранении заказа: {e}')
        else:

            messages.error(request, 'Пожалуйста, исправьте ошибки в форме.')
    else:
        form = OrderForm(instance=order)
        formset = OrderItemFormSet(instance=order)

    context = {
        'form': form,
        'formset': formset,
        'order': order,
        'title': f'Редактирование заказа #{order.order_number}',
        'button_text': 'Сохранить изменения',
    }

    return render(request, 'orders/order_form.html', context)


def order_delete(request, order_number):
    """Удаление заказа с подтверждением (только для черновиков без оплаты)"""
    order = get_object_or_404(Order, order_number=order_number)

    # Проверка: удалять можно только черновики
    if not order.status or order.status.code != 'draft':
        messages.error(
            request,
            f'Удаление невозможно. Удалять можно только заказы в статусе "Черновик". '
            f'Текущий статус: {order.status.name if order.status else "не задан"}'
        )
        return redirect('orders:order-detail', order_number=order.order_number)

    # Проверка: нельзя удалять заказы с оплатой
    if order.amount_paid > 0:
        messages.error(
            request,
            f'Удаление невозможно. Заказ имеет оплату ({order.amount_paid} руб.). '
            f'Сначала оформите возврат платежа.'
        )
        return redirect('orders:order-detail', order_number=order.order_number)

    # Проверка: нельзя удалять заказы с транзакциями кошелька
    if order.wallet_transactions.exists():
        messages.error(
            request,
            'Удаление невозможно. Заказ имеет транзакции кошелька клиента. '
            'Сначала удалите связанные транзакции.'
        )
        return redirect('orders:order-detail', order_number=order.order_number)

    if request.method == 'POST':
        order_number_saved = order.order_number
        order.delete()
        messages.success(request, f'Заказ #{order_number_saved} успешно удален.')
        return redirect('orders:order-list')

    context = {
        'order': order,
    }

    return render(request, 'orders/order_confirm_delete.html', context)


# === УПРАВЛЕНИЕ ТРАНЗАКЦИЯМИ ===

@login_required
@require_http_methods(["POST"])
def transaction_add_payment(request, order_number):
    """
    Добавление нового платежа к заказу.
    """
    from orders.services.transaction_service import TransactionService
    
    order = get_object_or_404(Order, order_number=order_number)
    
    form = TransactionForm(request.POST)
    
    if form.is_valid():
        try:
            # Создаём транзакцию платежа
            transaction = TransactionService.create_payment(
                order=order,
                amount=form.cleaned_data['amount'],
                payment_method=form.cleaned_data['payment_method'],
                user=request.user,
                notes=form.cleaned_data.get('notes')
            )
            
            messages.success(
                request, 
                f'Платёж на сумму {transaction.amount} руб. '
                f'({transaction.payment_method.name}) успешно добавлен.'
            )
        except (ValidationError, ValueError) as e:
            messages.error(request, f'Ошибка при добавлении платежа: {e}')
    else:
        # Показываем ошибки валидации
        for field, errors in form.errors.items():
            for error in errors:
                messages.error(request, f'{field}: {error}')
    
    # Возвращаемся на страницу редактирования
    return redirect('orders:order-update', order_number=order.order_number)


@login_required
@require_http_methods(["POST"])
def transaction_add_refund(request, order_number):
    """
    Добавление возврата по заказу.
    """
    from orders.services.transaction_service import TransactionService
    
    order = get_object_or_404(Order, order_number=order_number)
    
    amount = request.POST.get('refund_amount')
    payment_method_id = request.POST.get('refund_payment_method')
    reason = request.POST.get('refund_reason')
    notes = request.POST.get('refund_notes')
    
    try:
        amount = Decimal(amount)
        payment_method = get_object_or_404(PaymentMethod, pk=payment_method_id)
        
        # Создаём транзакцию возврата
        transaction = TransactionService.create_refund(
            order=order,
            amount=amount,
            payment_method=payment_method,
            user=request.user,
            reason=reason,
            notes=notes
        )
        
        messages.success(
            request, 
            f'Возврат на сумму {transaction.amount} руб. '
            f'({transaction.payment_method.name}) успешно создан.'
        )
    except (ValidationError, ValueError) as e:
        messages.error(request, f'Ошибка при создании возврата: {e}')
    
    return redirect('orders:order-update', order_number=order.order_number)


@login_required
@require_http_methods(["POST"])
def transaction_delete(request, order_number, transaction_id):
    """
    Удаление транзакции (не рекомендуется, лучше использовать refund).
    Оставлено для совместимости.
    """
    order = get_object_or_404(Order, order_number=order_number)
    transaction_obj = get_object_or_404(Transaction, pk=transaction_id, order=order)
    
    # Сохраняем данные для сообщения
    transaction_info = f'{transaction_obj.get_transaction_type_display()} {transaction_obj.payment_method.name} на сумму {transaction_obj.amount} руб.'
    
    # Предупреждение: удаление транзакций нарушает историю
    transaction_obj.delete()
    
    # Пересчитываем баланс
    order.recalculate_amount_paid()
    
    messages.warning(
        request, 
        f'Транзакция {transaction_info} удалена. '
        f'Рекомендуем использовать "Возврат" вместо удаления.'
    )
    return redirect('orders:order-update', order_number=order.order_number)


# === AJAX ENDPOINTS ===

@require_http_methods(["POST"])
@require_http_methods(["GET"])
@login_required
def get_customer_address_history(request):
    """
    AJAX endpoint для получения истории адресов клиента.

    GET параметры:
        - customer_id: ID клиента

    Возвращает JSON со списком адресов из истории заказов клиента.
    """
    try:
        customer_id = request.GET.get('customer_id')

        if not customer_id:
            return JsonResponse({
                'success': False,
                'error': 'customer_id не указан'
            }, status=400)

        from customers.models import Customer

        try:
            customer = Customer.objects.get(pk=customer_id)
        except Customer.DoesNotExist:
            return JsonResponse({
                'success': False,
                'error': 'Клиент не найден'
            }, status=404)

        # Получаем адреса из истории заказов
        addresses = AddressService.get_customer_address_history(customer)

        # Форматируем для отправки клиенту
        addresses_data = [
            {
                'id': addr.id,
                'display': AddressService.format_address_for_display(addr),
                'street': addr.street,
                'building_number': addr.building_number,
                'apartment_number': addr.apartment_number,
                'entrance': addr.entrance,
                'floor': addr.floor,
                'intercom_code': addr.intercom_code,
            }
            for addr in addresses
        ]

        return JsonResponse({
            'success': True,
            'addresses': addresses_data,
            'count': len(addresses_data)
        })

    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': f'Ошибка сервера: {str(e)}'
        }, status=500)


@require_http_methods(["GET"])
@login_required
def get_customer_recipient_history(request):
    """
    AJAX endpoint для получения истории получателей клиента.

    GET параметры:
        - customer_id: ID клиента

    Возвращает JSON со списком получателей из истории заказов клиента.
    """
    try:
        customer_id = request.GET.get('customer_id')

        if not customer_id:
            return JsonResponse({
                'success': False,
                'error': 'customer_id не указан'
            }, status=400)

        from customers.models import Customer
        from .models import Recipient

        try:
            customer = Customer.objects.get(pk=customer_id)
        except Customer.DoesNotExist:
            return JsonResponse({
                'success': False,
                'error': 'Клиент не найден'
            }, status=404)

        # Получаем получателей из истории заказов
        customer_orders = Order.objects.filter(
            customer=customer,
            recipient__isnull=False
        ).order_by('-created_at')
        
        recipients = Recipient.objects.filter(
            orders__in=customer_orders
        ).distinct().order_by('-created_at')

        # Форматируем для отправки клиенту
        recipients_data = [
            {
                'id': recipient.id,
                'name': recipient.name,
                'phone': recipient.phone,
                'display': f"{recipient.name} ({recipient.phone})",
            }
            for recipient in recipients
        ]

        return JsonResponse({
            'success': True,
            'recipients': recipients_data,
            'count': len(recipients_data)
        })

    except Exception as e:
        return JsonResponse({
            'success': False,
            'error': f'Ошибка сервера: {str(e)}'
        }, status=500)


# === УПРАВЛЕНИЕ СТАТУСАМИ ЗАКАЗОВ ===

@login_required
def order_status_list(request):
    """Список всех статусов заказов"""
    statuses = OrderStatus.objects.all().order_by('order', 'name')

    # orders_count уже доступен как property в модели OrderStatus
    # Не нужно вручную добавлять атрибут

    context = {
        'statuses': statuses,
        'title': 'Статусы заказов'
    }

    return render(request, 'orders/status_list.html', context)


@login_required
def order_status_create(request):
    """Создание нового статуса"""
    if request.method == 'POST':
        form = OrderStatusForm(request.POST)

        if form.is_valid():
            status = form.save(commit=False)
            status.created_by = request.user
            status.updated_by = request.user

            # Если не указан порядок - делаем его последним
            if not status.order:
                max_order = OrderStatus.objects.aggregate(models.Max('order'))['order__max'] or 0
                status.order = max_order + 10

            status.save()
            messages.success(request, f'Статус "{status.name}" успешно создан')
            return redirect('orders:status_list')
    else:
        form = OrderStatusForm()

    context = {
        'form': form,
        'title': 'Создать новый статус',
        'button_text': 'Создать'
    }

    return render(request, 'orders/status_form.html', context)


@login_required
def order_status_update(request, pk):
    """Редактирование статуса"""
    status = get_object_or_404(OrderStatus, pk=pk)

    if request.method == 'POST':
        form = OrderStatusForm(request.POST, instance=status)

        if form.is_valid():
            status = form.save(commit=False)
            status.updated_by = request.user
            status.save()
            messages.success(request, f'Статус "{status.name}" успешно обновлен')
            return redirect('orders:status_list')
    else:
        form = OrderStatusForm(instance=status)

    context = {
        'form': form,
        'status': status,
        'title': f'Редактировать статус: {status.name}',
        'button_text': 'Сохранить',
        'is_system': status.is_system
    }

    return render(request, 'orders/status_form.html', context)


@login_required
def order_status_delete(request, pk):
    """Удаление статуса"""
    status = get_object_or_404(OrderStatus, pk=pk)

    if status.is_system:
        messages.error(request, f'Нельзя удалить системный статус "{status.name}"')
        return redirect('orders:status_list')

    if request.method == 'POST':
        # Проверяем, что статус не используется в заказах
        orders_count = Order.objects.filter(status=status).count()

        if orders_count > 0:
            messages.error(
                request,
                f'Невозможно удалить статус. Есть {orders_count} заказов с этим статусом.'
            )
            return redirect('orders:status_list')

        status_name = status.name
        status.delete()
        messages.success(request, f'Статус "{status_name}" успешно удален')
        return redirect('orders:status_list')

    # Информация для подтверждения удаления
    orders_count = Order.objects.filter(status=status).count()

    context = {
        'status': status,
        'orders_count': orders_count,
        'title': 'Удалить статус'
    }

    return render(request, 'orders/status_confirm_delete.html', context)


# === ВРЕМЕННЫЕ КОМПЛЕКТЫ ===
# УДАЛЕНО: Логика создания временных комплектов перенесена в products.services.kit_service
# Используйте API endpoint: products:api-temporary-kit-create


# === КОШЕЛЁК КЛИЕНТА ===

@login_required
def apply_wallet_payment(request, order_number):
    """
    Применение оплаты из кошелька клиента к заказу.
    Вызывается через POST-запрос с суммой для списания.
    """
    if request.method != 'POST':
        return redirect('orders:order-detail', order_number=order_number)

    order = get_object_or_404(Order, order_number=order_number)

    # Получаем запрашиваемую сумму из формы
    try:
        raw_amount = request.POST.get('wallet_amount', '0')
        amount = Decimal(str(raw_amount).replace(',', '.'))
    except (ValueError, TypeError, ArithmeticError):
        messages.error(request, 'Некорректная сумма для списания из кошелька.')
        return redirect('orders:order-detail', order_number=order.order_number)

    # Вызываем сервис для оплаты из кошелька
    try:
        from customers.services.wallet_service import WalletService
        paid_amount = WalletService.pay_with_wallet(order, amount, request.user)

        if paid_amount and paid_amount > 0:
            messages.success(
                request,
                f'Из кошелька клиента списано {paid_amount} руб. для оплаты заказа #{order.order_number}.'
            )
        else:
            messages.warning(
                request,
                'Не удалось списать средства из кошелька. Проверьте баланс и сумму заказа.'
            )
    except ValueError as e:
        messages.error(request, str(e))
    except Exception as e:
        messages.error(request, f'Ошибка при оплате из кошелька: {str(e)}')

    return redirect('orders:order-detail', order_number=order.order_number)


@require_http_methods(["POST"])
@login_required
def set_order_status(request, order_number):
    """
    Update order status via AJAX.
    Accepts POST with 'status_id' (can be empty to clear).
    Returns JSON with the resulting status info.

    Использует транзакцию, чтобы при ошибке в сигналах (например, при создании Sale)
    статус откатился вместе со всеми связанными изменениями.
    """
    try:
        order = get_object_or_404(Order, order_number=order_number)
        status_id = request.POST.get('status_id', '').strip()

        # Allow clearing status if empty
        if status_id == '':
            with transaction.atomic():
                order.status = None
                order.modified_by = request.user
                order.save(update_fields=['status', 'modified_by', 'updated_at'])
            return JsonResponse({'success': True, 'status': None})

        try:
            status = OrderStatus.objects.get(pk=status_id)
        except OrderStatus.DoesNotExist:
            return JsonResponse({'success': False, 'error': 'Status not found'}, status=404)

        # Оборачиваем в транзакцию, чтобы при ошибке в сигналах статус откатился
        with transaction.atomic():
            order.status = status
            order.modified_by = request.user
            order.save(update_fields=['status', 'modified_by', 'updated_at'])

        return JsonResponse({
            'success': True,
            'status': {
                'id': status.pk,
                'name': status.label or status.name,
                'color': status.color
            }
        })
    except ValidationError as e:
        # Ошибка валидации (например, запрет смены статуса для возвращённого заказа)
        # Транзакция откатилась, статус НЕ изменился
        # Извлекаем чистое сообщение без служебных элементов
        error_message = str(e.message) if hasattr(e, 'message') else str(e)
        if hasattr(e, 'messages'):
            error_message = e.messages[0] if e.messages else str(e)
        return JsonResponse({'success': False, 'error': error_message}, status=400)
    except ValueError as e:
        # Ошибка в сигналах (например, не удалось создать Sale)
        # Транзакция откатилась, статус НЕ изменился
        return JsonResponse({'success': False, 'error': str(e)}, status=400)
    except Exception as e:
        return JsonResponse({'success': False, 'error': f'Server error: {str(e)}'}, status=500)


@login_required
@require_http_methods(["POST"])
def create_order_from_pos(request):
    """
    Создаёт отложенный заказ (черновик) из POS.
    Сразу создаёт Order со статусом 'draft' и резервирует ShowcaseItem.
    
    Payload (JSON):
    {
        "customer_id": int,
        "items": [
            {
                "type": "product"|"kit"|"showcase_kit",
                "id": int,
                "quantity": float,
                "price": float,
                "sales_unit_id": int,  // для product
                "showcase_item_ids": [int, ...]  // для showcase_kit
            }
        ]
    }
    
    Response:
    {
        "success": true,
        "order_number": int,
        "message": "Заказ #123 создан (черновик)"
    }
    """
    from .services.order_status_service import OrderStatusService
    from customers.models import Customer
    from products.models import Product, ProductKit
    from inventory.models import ShowcaseItem
    import logging
    
    logger = logging.getLogger(__name__)
    
    try:
        data = json.loads(request.body)
        customer_id = data.get('customer_id')
        items = data.get('items', [])
        
        if not customer_id:
            return JsonResponse({'success': False, 'error': 'Не указан клиент'}, status=400)
        
        if not items:
            return JsonResponse({'success': False, 'error': 'Корзина пуста'}, status=400)
        
        with transaction.atomic():
            # 1. Получаем клиента
            try:
                customer = Customer.objects.get(id=customer_id)
            except Customer.DoesNotExist:
                return JsonResponse({'success': False, 'error': 'Клиент не найден'}, status=404)
            
            # 2. Получаем статус 'Черновик'
            draft_status = OrderStatusService.get_draft_status()
            if not draft_status:
                return JsonResponse({
                    'success': False,
                    'error': 'Статус "Черновик" не найден. Выполните миграции.'
                }, status=500)
            
            # 3. Создаём заказ со статусом 'draft'
            order = Order.objects.create(
                customer=customer,
                status=draft_status,
                modified_by=request.user
            )
            
            # 4. Создаём OrderItem и резервируем ShowcaseItem
            for item_data in items:
                item_type = item_data.get('type')
                item_id = item_data.get('id')
                quantity = item_data.get('quantity', 1)
                price = item_data.get('price', 0)
                
                if item_type == 'product':
                    # Обычный товар
                    product = Product.objects.get(id=item_id)
                    sales_unit_id = item_data.get('sales_unit_id')
                    
                    OrderItem.objects.create(
                        order=order,
                        product=product,
                        sales_unit_id=sales_unit_id,
                        quantity=quantity,
                        price=price,
                        is_custom_price=False
                    )
                    
                elif item_type == 'kit':
                    # Обычный комплект
                    kit = ProductKit.objects.get(id=item_id)
                    
                    OrderItem.objects.create(
                        order=order,
                        product_kit=kit,
                        quantity=quantity,
                        price=price,
                        is_custom_price=False
                    )
                    
                elif item_type == 'showcase_kit':
                    # Витринный комплект - сразу резервируем ShowcaseItem
                    kit = ProductKit.objects.get(id=item_id)
                    showcase_item_ids = item_data.get('showcase_item_ids', [])
                    
                    if not showcase_item_ids:
                        logger.warning(f"⚠️ Пустой список showcase_item_ids для комплекта {kit.name}")
                        continue
                    
                    # Создаём OrderItem с флагом is_from_showcase
                    order_item = OrderItem.objects.create(
                        order=order,
                        product_kit=kit,
                        quantity=len(showcase_item_ids),
                        price=price,
                        is_custom_price=False,
                        is_from_showcase=True
                    )
                    
                    # Резервируем ShowcaseItem: in_cart → reserved
                    showcase_items = ShowcaseItem.objects.filter(
                        id__in=showcase_item_ids,
                        status='in_cart',
                        locked_by_user=request.user
                    )
                    
                    reserved_count = 0
                    component_count = 0
                    
                    for showcase_item in showcase_items:
                        showcase_item.reserve_for_order(order_item)
                        reserved_count += 1
                        
                        # КРИТИЧНО: Привязываем существующие резервы компонентов к OrderItem
                        # Эти резервы были созданы при добавлении букета на витрину
                        component_reservations = Reservation.objects.filter(
                            showcase_item=showcase_item,
                            status='reserved'
                        )
                        
                        for reservation in component_reservations:
                            reservation.order_item = order_item
                            reservation.save(update_fields=['order_item'])
                            component_count += 1
                    
                    logger.info(
                        f"✓ Витринный комплект '{kit.name}': зарезервировано {reserved_count} экз., "
                        f"привязано {component_count} резервов компонентов к OrderItem #{order_item.id}"
                    )
            
            # 5. Пересчитываем стоимость заказа
            order.calculate_total()
            order.update_payment_status()
            
            return JsonResponse({
                'success': True,
                'order_number': order.order_number,
                'message': f'Заказ #{order.order_number} создан (черновик)'
            })
        
    except json.JSONDecodeError:
        return JsonResponse({'success': False, 'error': 'Неверный формат JSON'}, status=400)
    except Product.DoesNotExist:
        return JsonResponse({'success': False, 'error': 'Товар не найден'}, status=404)
    except ProductKit.DoesNotExist:
        return JsonResponse({'success': False, 'error': 'Комплект не найден'}, status=404)
    except Exception as e:
        logger.error(f'Ошибка при создании отложенного заказа из POS: {str(e)}', exc_info=True)
        return JsonResponse({'success': False, 'error': f'Ошибка: {str(e)}'}, status=500)
