from django.db import models
from django.conf import settings
from products.models import Product, ProductVariation
from decimal import Decimal, InvalidOperation, ROUND_HALF_UP


def _to_decimal(value, default="0"):
    if value is None or value == "":
        return Decimal(default)
    if isinstance(value, Decimal):
        return value
    try:
        return Decimal(str(value))
    except (InvalidOperation, TypeError, ValueError):
        return Decimal(default)


class Cart(models.Model):
    """Shopping Cart"""
    
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='carts',
        null=True,
        blank=True
    )
    session_key = models.CharField(max_length=255, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        ordering = ['-updated_at']
    
    def __str__(self):
        if self.user:
            return f"Cart - {self.user.email}"
        return f"Cart - Session {self.session_key}"
    
    @property
    def total_items(self):
        return sum(item.quantity for item in self.items.all())
    
    @property
    def subtotal(self):
        val = sum(item.total_price for item in self.items.all())
        return val.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
    
    @property
    def shipping_cost(self):
        try:
            from ai_features.models import AIConfiguration
            config = AIConfiguration.get_settings()
            threshold = getattr(config, 'free_shipping_threshold', Decimal('500'))
            amount = getattr(config, 'shipping_flat_amount', Decimal('50'))
        except Exception:
            threshold = Decimal('500')
            amount = Decimal('50')
        
        if self.subtotal >= threshold:
            return Decimal('0.00')
        
        cost = amount if self.subtotal > 0 else Decimal('0')
        return cost.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
    
    @property
    def tax(self):
        try:
            from ai_features.models import AIConfiguration
            config = AIConfiguration.get_settings()
            rate_percent = getattr(config, 'tax_rate_percent', Decimal('18'))
        except Exception:
            rate_percent = Decimal('18')
        rate = (Decimal(str(rate_percent)) / Decimal('100'))
        tax_val = self.subtotal * rate if self.subtotal > 0 else Decimal('0')
        return tax_val.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
    
    @property
    def total(self):
        """Total = Subtotal + Shipping + Tax"""
        val = self.subtotal + self.shipping_cost + self.tax
        return val.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)


class CartItem(models.Model):
    """Cart Items"""
    
    cart = models.ForeignKey(
        Cart,
        on_delete=models.CASCADE,
        related_name='items'
    )
    product = models.ForeignKey(
        Product,
        on_delete=models.CASCADE
    )
    variation = models.ForeignKey(
        ProductVariation,
        on_delete=models.CASCADE,
        null=True,
        blank=True
    )
    quantity = models.IntegerField(default=1)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        unique_together = ('cart', 'product', 'variation')
        ordering = ['-created_at']
    
    def __str__(self):
        return f"{self.product.name} x {self.quantity}"
    
    @property
    def unit_price(self):
        # Check if product is on sale
        if self.product.is_sale_active:
             base = _to_decimal(self.product.sale_price, "0")
        else:
             base = _to_decimal(self.product.price, "0")

        if not self.variation:
            return base
        adj = _to_decimal(self.variation.price_adjustment, "0")
        if self.variation.quantity_unit in ('pcs', 'pair', 'set'):
            qty = _to_decimal(self.variation.quantity_value, "1")
            return (base * qty) + adj
        if self.variation.quantity_unit in ('m', 'cm', 'mm'):
            length = _to_decimal(self.variation.quantity_value, "1")
            if self.variation.quantity_unit == 'cm':
                length = length / Decimal('100')
            elif self.variation.quantity_unit == 'mm':
                length = length / Decimal('1000')
            return (base * length) + adj
        if self.variation.length:
            length = _to_decimal(self.variation.length, "1")
            unit = self.variation.dimension_unit or 'cm'
            if unit == 'cm':
                length = length / Decimal('100')
            elif unit == 'mm':
                length = length / Decimal('1000')
            elif unit == 'in':
                length = length * Decimal('0.0254')
            elif unit == 'ft':
                length = length * Decimal('0.3048')
            return (base * length) + adj
        return base + adj
    
    @property
    def total_price(self):
        qty = _to_decimal(self.quantity, "0")
        val = self.unit_price * qty
        return val.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
