from account.models import SpecialDiscountCode
from django.db import models, transaction
from account.models import User, UserAddressModel, PushSubscription
from product.models import ProductModel, ProductVariant, ProductImageModel
from django.utils import timezone
from django_jalali.db import models as jmodels
from django.core.exceptions import ValidationError
from django.conf import settings


class DiscountCode(models.Model):
    code = models.CharField(max_length=50, verbose_name='کد تخفیف')
    percent = models.DecimalField(
        max_digits=4, decimal_places=2, verbose_name='درصد')
    quantity = models.PositiveIntegerField(verbose_name='تعداد')
    expiration_date = models.DateTimeField(verbose_name='تاریخ انقضا')

    def __str__(self):
        return self.code

    class Meta:
        verbose_name = 'کد تخفیف'
        verbose_name_plural = 'کد های تخفیف'

    def is_valid(self):
        return self.expiration_date > timezone.now() and self.quantity > 0

    def not_valid_reason(self):
        if self.expiration_date > timezone.now() and self.quantity > 0:
            return 'این کد معتبر میباشد'
        elif not self.expiration_date > timezone.now():
            return 'تایم کد تخفیف تمام شده'
        elif not self.quantity > 0:
            return 'این کد تخفیف تمام شده است'
        else:
            print('log later bug')


class Cart(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='carts'
    )
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    address = models.ForeignKey(UserAddressModel, on_delete=models.SET_NULL,
                                related_name='carts', null=True, verbose_name='ادرس')
    discount_code = models.ForeignKey(
        DiscountCode, on_delete=models.PROTECT, null=True, blank=True, verbose_name="کدتخفیف")
    special_discount_code = models.ForeignKey(
        SpecialDiscountCode, on_delete=models.PROTECT, null=True, blank=True, verbose_name="کدتخفیف خاص")

    class Meta:
        verbose_name = 'سبد خرید'
        verbose_name_plural = 'سبد های خرید'

    def __str__(self):
        return f"Cart for {self.user.email}"

    def clear_cart(self):
        self.items.all().delete()
        self.discount_code = None
        self.special_discount_code = None
        self.save()

    @property
    def discount_code_amount(self):
        if self.discount_code:
            return int(int(self.cart_total - self.items_discount_amount) * (self.discount_code.percent / 100))
        else:
            return 0

    @property
    def items_discount_amount(self):
        return int(sum(item.item_discount_amount for item in self.items.all()))

    @property
    def special_discount_total(self):
        """Sum of all special discounts from cart items when special_discount_code is applied."""
        if self.special_discount_code:
            return int(sum(item.item_special_discount_amount for item in self.items.all()))
        return 0

    @property
    def total_before_tax(self):
        return self.cart_total - (self.discount_code_amount + self.items_discount_amount + self.special_discount_total)

    @property
    def tax_amount(self):
        return int(self.total_before_tax * settings.DEFAULT_TAX_RATE / 100)

    @property
    def cart_total(self):
        return sum(item.price_before_discount for item in self.items.all())

    @property
    def final_price(self):
        return self.total_before_tax + self.tax_amount


class CartItem(models.Model):
    cart = models.ForeignKey(
        Cart,
        on_delete=models.CASCADE,
        related_name='items'
    )
    product_variant = models.ForeignKey(
        ProductVariant,
        on_delete=models.CASCADE,
        related_name='cart_items'
    )
    quantity = models.PositiveIntegerField(default=1)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    # special_discount_amount = models.BigIntegerField(default=0, verbose_name='مقدار تخفیف ویژه', help_text='تخفیف محاسبه شده از سود تنوع')

    class Meta:
        verbose_name = 'ایتم سبد خرید'
        verbose_name_plural = 'ایتم های سبد خرید'
        unique_together = ('cart', 'product_variant')

    def __str__(self):
        return f"{self.quantity} x {self.product_variant.product.name} in cart {self.cart.id}"

    @property
    def special_discount_amount(self):
        """Calculate special discount for this cart item based on variant profit and special_discount_percent."""
        if hasattr(self.cart, 'special_discount_code') and self.cart.special_discount_code:
            return self.product_variant.special_discount_amount_per_unit * self.quantity
        return 0

    @property
    def price_before_discount(self):
        return self.quantity * self.product_variant.price_before_discount

    @property
    def item_discount_amount(self):
        return self.product_variant.discount_amount * self.quantity

    @property
    def item_special_discount_amount(self):
        """Calculate special discount for this cart item based on variant profit and special_discount_percent."""
        if hasattr(self.cart, 'special_discount_code') and self.cart.special_discount_code:
            return self.product_variant.special_discount_amount_per_unit * self.quantity
        return 0

    @property
    def price_after_discount(self):
        return self.price_before_discount - self.item_discount_amount - self.item_special_discount_amount

    @property
    def discount(self):
        return self.product_variant.discount


class OrderModel(models.Model):
    objects = jmodels.jManager()
    STATUS_CHOICES = [
        ('ADMIN_PENDING', 'در انتظار تایید'),
        ('PENDING', 'درحال پردازش'),
        ('POSTED', 'ارسال شده'),
        ('RECEIVED', 'تحویل شده'),
        ('CANCELED', 'لغو شده'),
        ('REFUNDED', 'مرجوع شده'),
    ]
    user = models.ForeignKey(User, on_delete=models.SET_NULL,
                             null=True, related_name='orders', verbose_name='کاربر')
    address = models.ForeignKey(UserAddressModel, on_delete=models.SET_NULL,
                                related_name='orders', null=True, verbose_name='ادرس')
    created_at = jmodels.jDateField(
        blank=True, null=True, verbose_name="تاریخ ثبت سفارش")
    is_paid = models.BooleanField(default=False, verbose_name="وضعیت پرداخت")
    discount_code = models.ForeignKey(
        DiscountCode, on_delete=models.PROTECT, null=True, blank=True, verbose_name="کدتخفیف")
    special_discount_code = models.ForeignKey(
        SpecialDiscountCode, on_delete=models.PROTECT, null=True, blank=True, verbose_name="کدتخفیف خاص")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES,
                              default='ADMIN_PENDING', verbose_name="وضعیت سفارش")
    discount_amount = models.BigIntegerField(
        null=True, blank=True, verbose_name='مقدار کد تخفیف')
    tax = models.BigIntegerField(null=True, blank=True, verbose_name='مالیات')
    final_price = models.BigIntegerField(
        null=True, blank=True, verbose_name='قیمت نهایی')
    cart_total = models.BigIntegerField(
        null=True, blank=True, verbose_name='کل سبد خرید')
    special_discount_total = models.BigIntegerField(
        null=True, blank=True, verbose_name='مجموع تخفیف ویژه')

    cart = models.ForeignKey(
        Cart, on_delete=models.CASCADE, null=True, blank=True)

    is_stock_rolled_back = models.BooleanField(
        default=False, verbose_name="موجودی برگردانده شده")

    def __str__(self):
        return f'سفارش: {self.pk}'

    class Meta:
        verbose_name = 'سفارش'
        verbose_name_plural = 'سفارشات'

    def rollback_stock(self):
        """
        Rollback stock quantities for all items in this order
        Returns True if successful, False otherwise
        """
        if self.is_stock_rolled_back:
            return False

        # if not self.cart:
        #     return False

        try:
            # Get all cart items and rollback their stock
            for order_item in self.items.all():
                product = order_item.product
                # Add back the quantity to stock
                product.in_stock += order_item.quantity
                product.save()

            # Mark as rolled back
            self.is_stock_rolled_back = True
            self.save(update_fields=['is_stock_rolled_back'])
            self.status = 'CANCELED'
            self.save()
            return True

        except Exception as e:
            print(e)
            # Log the error if you have logging setup
            # logger.error(f"Failed to rollback stock for order {self.pk}: {e}")
            return False


class OrderItemModel(models.Model):
    order = models.ForeignKey(
        OrderModel, on_delete=models.CASCADE, related_name='items', verbose_name='سفارش')
    quantity = models.PositiveSmallIntegerField(verbose_name="تعداد")
    price = models.BigIntegerField(verbose_name='قیمت')
    product = models.ForeignKey(
        ProductVariant, on_delete=models.PROTECT, verbose_name="محصول")
    discount_percent = models.SmallIntegerField(verbose_name='درصد تخفیف')
    special_discount_amount = models.BigIntegerField(
        default=0, verbose_name='مقدار تخفیف ویژه')

    class Meta:
        verbose_name = 'ایتم سبد خرید'
        verbose_name_plural = 'ایتم های سبد خرید'

    def __str__(self):
        return f'({self.product}) - ({self.order.user})'
    
    # @property
    def total_price_before_discount(self):
        return self.price * self.quantity
    
    # @property
    def total_product_discount_amount(self):
        if self.discount_percent > 0:
            return int((self.price * self.quantity) * (self.discount_percent / 100))
        return 0
    
    # @property
    def price_after_special_discount(self):
        all_discounts = (self.special_discount_amount or 0) + self.total_product_discount_amount()
        print(all_discounts)
        return self.total_price_before_discount() - all_discounts
    
    def unit_price(self):
        return self.price

class ShopOrderModel(models.Model):
    """Represents the portion of a customer Order that belongs to a single Shop.

    This model is created automatically when an `OrderModel` is finalized/paid.
    It holds aggregated financial details for that shop (subtotal, discounts,
    commission and final payable amount).
    """
    order = models.ForeignKey(OrderModel, on_delete=models.CASCADE, related_name='shop_orders')
    shop = models.ForeignKey('account.ShopModel', on_delete=models.CASCADE, related_name='shop_orders')
    daily_report = models.ForeignKey('ShopDailyReport', on_delete=models.SET_NULL, null=True, blank=True, related_name='shop_orders', verbose_name='گزارش روزانه')
    
    # Customer Information
    customer = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='مشتری')
    customer_phone = models.CharField(max_length=12, verbose_name='شماره تلفن مشتری', blank=True)
    customer_name = models.CharField(max_length=100, verbose_name='نام مشتری', blank=True)
    
    # Delivery Address (ForeignKey + text backup)
    address = models.ForeignKey(UserAddressModel, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='آدرس تحویل')
    address_text = models.TextField(verbose_name='آدرس کامل', blank=True)
    address_postal_code = models.CharField(max_length=10, verbose_name='کد پستی', blank=True)
    address_phone = models.CharField(max_length=11, verbose_name='شماره تماس تحویل گیرنده', blank=True)
    address_city = models.CharField(max_length=30, verbose_name='شهر', blank=True)
    address_province = models.CharField(max_length=30, verbose_name='استان', blank=True)
    address_recipient_name = models.CharField(max_length=100, verbose_name='نام تحویل گیرنده', blank=True)
    
    # Order Status & Payment
    STATUS_CHOICES = [
        ('ADMIN_PENDING', 'در انتظار تایید'),
        ('PENDING', 'درحال پردازش'),
        ('POSTED', 'ارسال شده'),
        ('RECEIVED', 'تحویل شده'),
        ('CANCELED', 'لغو شده'),
        ('REFUNDED', 'مرجوع شده'),
    ]
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='ADMIN_PENDING', verbose_name='وضعیت سفارش')
    is_paid = models.BooleanField(default=False, verbose_name='وضعیت پرداخت')
    
    # Financial Details
    subtotal = models.BigIntegerField(verbose_name='جمع جزئیات', default=0)
    items_count = models.PositiveIntegerField(default=0)
    discount_amount = models.BigIntegerField(default=0, verbose_name='تخفیف اختصاصی فروشگاه')
    special_discount_code = models.ForeignKey(
        'account.SpecialDiscountCode', on_delete=models.PROTECT, null=True, blank=True, verbose_name='کدتخفیف خاص')
    special_discount_amount = models.BigIntegerField(default=0, verbose_name='تخفیف ویژه اختصاصی')
    commission_percent = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='درصد کمیسیون')
    commission_amount = models.BigIntegerField(default=0, verbose_name='مبلغ کمیسیون')
    tax_amount = models.BigIntegerField(default=0, verbose_name='مالیات')
    payable_amount = models.BigIntegerField(default=0, verbose_name='قابل پرداخت به فروشگاه')
    is_settled = models.BooleanField(default=False, verbose_name='تسویه شده')
    
    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    order_created_at = models.DateTimeField(null=True, blank=True, verbose_name='تاریخ ثبت سفارش اصلی')

    class Meta:
        verbose_name = 'سفارش به ازای فروشگاه'
        verbose_name_plural = 'سفارشات به ازای فروشگاه'

    def __str__(self):
        return f'ShopOrder({self.shop.shop_name}) for Order {self.order.pk}'


class ShopOrderItem(models.Model):
    shop_order = models.ForeignKey(ShopOrderModel, on_delete=models.CASCADE, related_name='items')
    order_item = models.ForeignKey(OrderItemModel, on_delete=models.PROTECT, related_name='shop_items')
    quantity = models.PositiveIntegerField()
    unit_price = models.BigIntegerField()
    total_price = models.BigIntegerField()
    discount_amount = models.BigIntegerField(default=0)
    special_discount_amount = models.BigIntegerField(default=0)

    class Meta:
        verbose_name = 'ایتم سفارش فروشگاه'
        verbose_name_plural = 'ایتم های سفارش فروشگاه'

    def __str__(self):
        return f'{self.order_item} for {self.shop_order}'


class ShopDailyReport(models.Model):
    """Daily aggregated report per shop. Run once per day to record totals."""
    shop = models.ForeignKey('account.ShopModel', on_delete=models.CASCADE, related_name='daily_reports')
    date = models.DateField()
    total_sales = models.BigIntegerField(default=0)
    total_commission = models.BigIntegerField(default=0)
    total_payable = models.BigIntegerField(default=0)
    is_settled = models.BooleanField(default=False, verbose_name='تسویه شده')
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = 'گزارش روزانه فروشگاه'
        verbose_name_plural = 'گزارش های روزانه فروشگاه'
        unique_together = (('shop', 'date'),)

    def __str__(self):
        return f'Report {self.shop.shop_name} - {self.date}'
