from decimal import Decimal
from django.core.exceptions import ValidationError


class DiscountValidator:
    """
    Сервис для валидации скидок и промокодов.
    """

    @staticmethod
    def validate_promo_code(code, customer=None, order_subtotal=None):
        """
        Валидировать промокод.

        Args:
            code: Код промокода
            customer: Customer для проверки использований
            order_subtotal: Сумма заказа для проверки min_order_amount

        Returns:
            tuple: (is_valid, promo_code_or_none, error_message)
        """
        from discounts.models import PromoCode

        if not code or not code.strip():
            return False, None, "Промокод не указан"

        try:
            promo = PromoCode.objects.get(
                code__iexact=code.strip().upper(),
                is_active=True
            )
        except PromoCode.DoesNotExist:
            return False, None, "Промокод не найден"

        # Проверяем валидность промокода
        is_valid, error = promo.is_valid(customer)
        if not is_valid:
            return False, None, error

        # Проверяем мин. сумму заказа
        if order_subtotal is not None and promo.discount.min_order_amount:
            if Decimal(order_subtotal) < promo.discount.min_order_amount:
                return False, None, f"Минимальная сумма заказа: {promo.discount.min_order_amount} руб."

        # Проверяем scope (только заказ, не товары)
        if promo.discount.scope not in ('order', 'product', 'category'):
            return False, None, "Этот тип промокода не поддерживается"

        return True, promo, None

    @staticmethod
    def validate_discount_for_order(discount, order):
        """
        Проверить, можно ли применить скидку к заказу.

        Args:
            discount: Discount
            order: Order

        Returns:
            tuple: (is_valid, error_message)
        """
        if not discount.is_active:
            return False, "Скидка неактивна"

        # Проверяем даты
        if not discount.is_valid_now():
            return False, "Скидка недействительна"

        # Проверяем мин. сумму заказа
        if discount.scope == 'order' and discount.min_order_amount:
            if order.subtotal < discount.min_order_amount:
                return False, f"Минимальная сумма заказа: {discount.min_order_amount} руб."

        return True, None

    @staticmethod
    def validate_auto_discount_for_cart(discount, cart_subtotal, customer=None):
        """
        Проверить, можно ли применить автоматическую скидку к корзине.

        Args:
            discount: Discount
            cart_subtotal: Десятичное число - сумма корзины
            customer: Customer (опционально)

        Returns:
            bool: True если скидка применима
        """
        if not discount.is_auto:
            return False

        if not discount.is_valid_now():
            return False

        if discount.scope == 'order' and discount.min_order_amount:
            if cart_subtotal < discount.min_order_amount:
                return False

        return True
