from decimal import Decimal
from django.conf import settings
from product.models import Product
from .models import Cart as CartModel, CartItem

class Cart(object):
    def __init__(self, request):
        """
        Initialize the cart.
        """
        self.session = request.session
        self.user = request.user
        
        # Session cart initialization
        cart = self.session.get(settings.CART_SESSION_ID)
        if not cart:
            cart = self.session[settings.CART_SESSION_ID] = {}
        self.cart = cart

    def add(self, product, quantity=1, override_quantity=False):
        """
        Add a product to the cart or update its quantity.
        """
        if self.user.is_authenticated:
            self._add_db(product, quantity, override_quantity)
        else:
            self._add_session(product, quantity, override_quantity)

    def _add_session(self, product, quantity, override_quantity):
        product_id = str(product.id)
        if product_id not in self.cart:
            self.cart[product_id] = {'quantity': 0, 'price': str(product.price)}
        
        if override_quantity:
            self.cart[product_id]['quantity'] = quantity
        else:
            self.cart[product_id]['quantity'] += quantity
            
        if self.cart[product_id]['quantity'] <= 0:
            self.remove(product)
        else:
            self.save()

    def _add_db(self, product, quantity, override_quantity):
        cart, created = CartModel.objects.get_or_create(user=self.user)
        cart_item, item_created = CartItem.objects.get_or_create(cart=cart, product=product)
        
        if override_quantity:
            cart_item.quantity = quantity
        else:
            if not item_created:
                cart_item.quantity += quantity
            else:
                cart_item.quantity = quantity # Yeni oluşturulduysa zaten default 1 değil, gelen quantity olmalı
        
        if cart_item.quantity <= 0:
            cart_item.delete()
        else:
            cart_item.save()

    def save(self):
        # mark the session as "modified" to make sure it gets saved
        self.session.modified = True

    def remove(self, product):
        """
        Remove a product from the cart.
        """
        if self.user.is_authenticated:
            CartItem.objects.filter(cart__user=self.user, product=product).delete()
        else:
            product_id = str(product.id)
            if product_id in self.cart:
                del self.cart[product_id]
                self.save()

    def __iter__(self):
        """
        Iterate over the items in the cart and get the products
        from the database.
        """
        if self.user.is_authenticated:
            # DB'den oku
            cart, created = CartModel.objects.get_or_create(user=self.user)
            for item in cart.items.select_related('product').all():
                yield {
                    'product': item.product,
                    'quantity': item.quantity,
                    'price': Decimal(item.product.price),
                    'total_price': Decimal(item.product.price) * item.quantity
                }
        else:
            # Session'dan oku
            product_ids = self.cart.keys()
            products = Product.objects.filter(id__in=product_ids)
            cart = self.cart.copy()
            for product in products:
                cart[str(product.id)]['product'] = product
            for item in cart.values():
                item['price'] = Decimal(item['price'])
                item['total_price'] = item['price'] * item['quantity']
                yield item

    def __len__(self):
        """
        Count all items in the cart.
        """
        if self.user.is_authenticated:
            cart, created = CartModel.objects.get_or_create(user=self.user)
            return sum(item.quantity for item in cart.items.all())
        else:
            return sum(item['quantity'] for item in self.cart.values())

    def get_total_price(self):
        if self.user.is_authenticated:
            cart, created = CartModel.objects.get_or_create(user=self.user)
            return sum(item.total_price for item in cart.items.all())
        else:
            return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())

    def clear(self):
        if self.user.is_authenticated:
            cart, created = CartModel.objects.get_or_create(user=self.user)
            cart.items.all().delete()
        else:
            del self.session[settings.CART_SESSION_ID]
            self.save()
