"""
Сервисы для расчета цен комплектов (ProductKit).
Извлекает сложную бизнес-логику из модели.
"""
from decimal import Decimal, InvalidOperation
import logging

logger = logging.getLogger(__name__)


class KitPriceCalculator:
    """
    Калькулятор цен для ProductKit.
    Реализует различные методы ценообразования комплектов.
    """

    @staticmethod
    def calculate_price_with_substitutions(kit, stock_manager=None):
        """
        Расчёт цены комплекта с учётом доступных замен компонентов.

        Метод определяет цену комплекта, учитывая доступные товары-заменители
        и применяет выбранный метод ценообразования.

        Args:
            kit (ProductKit): Комплект для расчета
            stock_manager: Объект управления складом (если не указан, используется стандартный)

        Returns:
            Decimal: Расчетная цена комплекта, или 0 в случае ошибки
        """
        from ..utils.stock_manager import StockManager

        if stock_manager is None:
            stock_manager = StockManager()

        # Если указана ручная цена, используем её
        if kit.pricing_method == 'manual' and kit.price:
            return kit.price

        total_cost = Decimal('0.00')
        total_sale = Decimal('0.00')

        for kit_item in kit.kit_items.select_related('product', 'variant_group'):
            try:
                best_product = kit_item.get_best_available_product(stock_manager)

                if not best_product:
                    # Если товар недоступен, используем цену первого в списке
                    available_products = kit_item.get_available_products()
                    best_product = available_products[0] if available_products else None

                if best_product:
                    item_cost = best_product.cost_price
                    item_price = best_product.price
                    item_quantity = kit_item.quantity or Decimal('1.00')

                    # Проверяем корректность значений перед умножением
                    if item_cost and item_quantity:
                        total_cost += item_cost * item_quantity
                    if item_price and item_quantity:
                        total_sale += item_price * item_quantity
            except (AttributeError, TypeError, InvalidOperation) as e:
                # Логируем ошибку, но продолжаем вычисления
                logger.warning(
                    f"Ошибка при расчёте цены для комплекта {kit.name} (item: {kit_item}): {e}"
                )
                continue  # Пропускаем ошибочный элемент и продолжаем с остальными

        # Применяем метод ценообразования
        try:
            if kit.pricing_method == 'from_sale_prices':
                return total_sale
            elif kit.pricing_method == 'from_cost_plus_percent' and kit.markup_percent is not None:
                return total_cost * (Decimal('1') + kit.markup_percent / Decimal('100'))
            elif kit.pricing_method == 'from_cost_plus_amount' and kit.markup_amount is not None:
                return total_cost + kit.markup_amount
            elif kit.pricing_method == 'manual' and kit.price:
                return kit.price

            return total_sale
        except (TypeError, InvalidOperation) as e:
            logger.error(
                f"Ошибка при применении метода ценообразования для комплекта {kit.name}: {e}"
            )
            # Возвращаем ручную цену если есть, иначе 0
            if kit.pricing_method == 'manual' and kit.price:
                return kit.price
            return Decimal('0.00')


class KitCostCalculator:
    """
    Калькулятор себестоимости для ProductKit.
    Включает расчет и валидацию себестоимости комплекта.
    """

    @staticmethod
    def calculate_cost(kit):
        """
        Расчёт себестоимости комплекта на основе себестоимости компонентов.

        Args:
            kit (ProductKit): Комплект для расчета

        Returns:
            Decimal: Себестоимость комплекта (может быть 0 если есть проблемы)
        """
        total_cost = Decimal('0.00')

        for kit_item in kit.kit_items.select_related('product', 'variant_group'):
            # Получаем продукт - либо конкретный, либо первый из группы вариантов
            product = kit_item.product
            if not product and kit_item.variant_group:
                # Берем первый продукт из группы вариантов
                product = kit_item.variant_group.products.filter(status='active').first()

            if product and product.cost_price:
                item_cost = product.cost_price
                item_quantity = kit_item.quantity or Decimal('1.00')
                total_cost += item_cost * item_quantity

        return total_cost

    @staticmethod
    def validate_and_calculate_cost(kit):
        """
        Расчёт себестоимости с полной валидацией.
        Проверяет, что все компоненты имеют себестоимость > 0.

        Args:
            kit (ProductKit): Комплект для валидации и расчета

        Returns:
            dict: {
                'total_cost': Decimal or None,
                'is_valid': bool,
                'problems': list of dicts {
                    'component_name': str,
                    'reason': str,
                    'kit_item_id': int
                }
            }
        """
        total_cost = Decimal('0.00')
        problems = []

        if not kit.kit_items.exists():
            # Комплект без компонентов не может иметь корректную себестоимость
            return {
                'total_cost': None,
                'is_valid': False,
                'problems': [{
                    'component_name': 'Комплект',
                    'reason': 'Комплект не содержит компонентов'
                }]
            }

        for kit_item in kit.kit_items.select_related('product', 'variant_group'):
            # Получаем продукт
            product = kit_item.product
            product_name = ''

            if not product and kit_item.variant_group:
                # Берем первый активный продукт из группы вариантов
                product = kit_item.variant_group.products.filter(status='active').first()
                if kit_item.variant_group:
                    product_name = f"[Варианты] {kit_item.variant_group.name}"

            if not product:
                # Товар не найден или группа вариантов пуста
                if kit_item.variant_group:
                    problems.append({
                        'component_name': f"[Варианты] {kit_item.variant_group.name}",
                        'reason': 'Группа не содержит активных товаров',
                        'kit_item_id': kit_item.id
                    })
                else:
                    problems.append({
                        'component_name': 'Неизвестный компонент',
                        'reason': 'Товар не выбран и нет группы вариантов',
                        'kit_item_id': kit_item.id
                    })
                continue

            # Используем имя товара, если не установили выше
            if not product_name:
                product_name = product.name

            # Проверяем наличие себестоимости
            if product.cost_price is None:
                problems.append({
                    'component_name': product_name,
                    'reason': 'Себестоимость не определена',
                    'kit_item_id': kit_item.id
                })
                continue

            # Проверяем, что себестоимость > 0
            if product.cost_price == Decimal('0.00') or product.cost_price <= 0:
                problems.append({
                    'component_name': product_name,
                    'reason': 'Себестоимость равна 0',
                    'kit_item_id': kit_item.id
                })
                continue

            # Если всё OK - добавляем в сумму
            try:
                item_quantity = kit_item.quantity or Decimal('1.00')
                if item_quantity > 0:
                    total_cost += product.cost_price * item_quantity
            except (TypeError, InvalidOperation) as e:
                logger.warning(
                    f"Ошибка при расчете себестоимости компонента {product_name} "
                    f"комплекта {kit.name}: {e}"
                )
                problems.append({
                    'component_name': product_name,
                    'reason': 'Ошибка при расчете',
                    'kit_item_id': kit_item.id
                })

        # Если есть проблемы, себестоимость не валидна
        is_valid = len(problems) == 0

        return {
            'total_cost': total_cost if is_valid else None,
            'is_valid': is_valid,
            'problems': problems
        }
