from rest_framework import serializers
from decimal import Decimal
from .models import *
from product.serializers import *
from address.serializers import *
from django.db import transaction
from wallet.models import ShoppingPoint
from collections import defaultdict

class CartSerializer(serializers.ModelSerializer):

    product_details = ProductSerializer(source='product', read_only=True) 
    product_price = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)


    class Meta:
        model = Cart
        fields = ['id', 'buyer', 'product', 'product_details', 'product_price', 'color', 'size', 'quantity', 'total','created_at','updated_at']
        read_only_fields = ['buyer', 'total', 'product_price'] 

    def validate_product_price(self, value):
        if value <= 0:
            raise serializers.ValidationError("Please enter a valid product price.")
        return value

    def validate_quantity(self, value):
        if value <= 0:
            raise serializers.ValidationError("Quantity must be greater than zero.")

        # product = self.initial_data.get('product')  
        # if product:
        #     product_instance = Product.objects.filter(id=product).first()
        #     if product_instance and value > product_instance.quantity:
        #         raise serializers.ValidationError("Requested quantity exceeds available stock.")

        return value
    
    def validate_color(self, value):
        if value in ['', None]:
            return None
        return value
    
    def validate_size(self, value):
        if value in ['', None]:
            return None
        return value
    
class OrderSerializer(serializers.Serializer):

    total_item_amount = serializers.DecimalField(max_digits=16, decimal_places=2, required=True, error_messages={"required": "Item subtotal is required."})
    tax_percentage = serializers.DecimalField(max_digits=16, decimal_places=2, required=True, error_messages={"required": "Tax percentage is required."})
    total_tax_amount = serializers.DecimalField(max_digits=16, decimal_places=2, required=True, error_messages={"required": "Tax amount is required."})
    free_shipping_amount = serializers.DecimalField(max_digits=16, decimal_places=2, required=True, error_messages={"required": "Free shipping amount is required."})
    shipping_fee_percentage = serializers.DecimalField(max_digits=16, decimal_places=2, required=True, error_messages={"required": "Shipping fee percentage is required."})
    shipping_fee = serializers.DecimalField(max_digits=16, decimal_places=2, required=True, error_messages={"required": "Shipping fee is required."})
    shopping_point = serializers.DecimalField(max_digits=16, decimal_places=2, required=False)
    platform_fee = serializers.DecimalField(max_digits=16, decimal_places=2, required=True, error_messages={"required": "Platform fee is required."})
    grand_total = serializers.DecimalField(max_digits=16, decimal_places=2, required=True, error_messages={"required": "Total amount is required."})
    payment_status = serializers.ChoiceField(choices=OrderPurchase.PaymentStatus.choices, required=True, error_messages={"required": "Payment status is required."})
    transaction_id = serializers.CharField(required=True, error_messages={"required": "Transaction ID is required."})

    class Meta:
        model = OrderPurchase
        fileds = ['buyer', 'total_item_amount', 'tax_percentage', 'total_tax_amount', 'platform_fee', 'shipping_fee_percentage', 'shipping_fee', 'free_shipping_amount', 'shopping_point', 'grand_total', 'order_status', 'payment_status','created_at','updated_at']

    def validate(self, data):
        request = self.context.get("request")
        buyer = request.user if request else None  
        
        if not buyer:
            raise serializers.ValidationError({"buyer": "Authentication required."})

        if not Cart.objects.filter(buyer=buyer).exists():
            raise serializers.ValidationError({"cart": "No items found in the cart."})

        data["buyer"] = buyer 
        return data
    
    def create(self, validated_data):   
        validated_data.pop('transaction_id')
        buyer = validated_data['buyer']
        cart_items = Cart.objects.filter(buyer=buyer)
       
        if not cart_items.exists():
            raise serializers.ValidationError({"cart": "Cart is empty."})
        tax_percentage = validated_data["tax_percentage"]

        with transaction.atomic():
            # Create the OrderPurchase
            validated_data["order_status"] = OrderPurchase.OrderStatus.CONFIRMED 

            address = Address.objects.filter(user=buyer).first()
            if address:
                validated_data["address"] = f"{address.address}, {address.city}, {address.district}, {address.country}"

            order = OrderPurchase.objects.create(**validated_data)
          

            order_items = []
            for cart_item in cart_items:
                vendor = cart_item.product.user  

                calculated_tax_amount = (cart_item.total * tax_percentage) / Decimal(100)

                order_items.append(
                    OrderItem(
                        order_purchase=order,
                        buyer=buyer,
                        product=cart_item.product,
                        vendor=vendor,  
                        product_price=cart_item.product_price,
                        color=cart_item.color,
                        size=cart_item.size,
                        origin_product_price=cart_item.origin_product_price,
                        quantity=cart_item.quantity,
                        sub_total=cart_item.total,
                        tax_percentage=tax_percentage,
                        tax_amount=calculated_tax_amount,  
                        total=cart_item.total + calculated_tax_amount, 
                        delivery_status="pending"
                    )
                )

            try:
                OrderItem.objects.bulk_create(order_items)
                
                product_sales = defaultdict(int)

                for cart_item in cart_items:
                    if cart_item.product:  # Ensure product exists
                        product_sales[cart_item.product.id] += cart_item.quantity

                # Update sold_quantity for each product
                for product_id, total_qty in product_sales.items():
                    try:
                        product = Product.objects.get(id=product_id)
                        product.sold_quantity += total_qty
                        product.save(update_fields=['sold_quantity'])
                        
                        logger.info(
                            f"[Order #{order.id}] Product #{product.id} sold_quantity increased by {total_qty}. "
                            f"New sold_quantity: {product.sold_quantity}"
                        )
                    except Product.DoesNotExist:
                        logger.warning(f"[Order #{order.id}] Product with ID {product_id} not found. Cannot update sold_quantity.")
                # for cart_item in cart_items:
                #     product = cart_item.product
                #     product.sold_quantity += cart_item.quantity
                #     product.save(update_fields=['sold_quantity'])
                #      # Logging
                #     print(f"[Order #{order.id}] Product #{product.id} sold_quantity updated by {cart_item.quantity}. New sold_quantity: {product.sold_quantity}")

                shopping_point_used = validated_data.get("shopping_point", 0)

                if shopping_point_used:
                    shopping_point_used = Decimal(shopping_point_used)

                    # Deduct points from user
                    actual_deducted = min(buyer.total_points or 0, shopping_point_used)

                    print(f"actual_deducted - {actual_deducted}, shopping_point_used - {shopping_point_used} ")

                    buyer.total_points = (buyer.total_points or 0) - actual_deducted
                    buyer.save()

                    # Create a ShoppingPoint entry
                    ShoppingPoint.objects.create(
                        user=buyer,
                        transaction_type='debit',
                        points=shopping_point_used,
                        description=f"Shopping Points used on Order #{order.id}",
                        order=order
                    )

                cart_items.delete()  # Delete cart items only if no error occurs
            except Exception as e:
                print(f"Error creating order items: {e}")

            # OrderItem.objects.bulk_create(order_items)
            # cart_items.delete()
            # cart_items.update(deleted_at=now())
            # for cart_item in cart_items:
            #     cart_item.soft_delete()

        return order
    

class OrderTransactionSerializer(serializers.ModelSerializer):
    transaction_id = serializers.CharField(required=True, error_messages={"required": "Transaction ID is required."})
    order_purchase = serializers.PrimaryKeyRelatedField(queryset=OrderPurchase.objects.all(), required=True)
    buyer = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), required=True)
    payment_status = serializers.ChoiceField(choices=OrderTransaction.PaymentStatus.choices, required=True)
    # payment_method = serializers.ChoiceField(choices=OrderTransaction.PaymentMethod.choices, required=True)
    amount = serializers.DecimalField(max_digits=16, decimal_places=2, required=True)

    class Meta:
        model = OrderTransaction
        fields = ["buyer","transaction_id", "order_purchase", "payment_status", "payment_method", "amount", "created_at"]

    def validate_amount(self, value):
        if value <= Decimal(0):
            raise serializers.ValidationError("Total amount must be greater than zero.")
        return value
    
class OrderItemFlagUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderItem
        fields = ['id', 'is_shipped', 'is_delivered', 'is_received','delivery_status','delivery_date']

class TransactionDetailsSerializer(serializers.ModelSerializer):
    payment_method = serializers.ChoiceField(choices=OrderTransaction.PaymentMethod.choices, source="get_payment_method_display")
    payment_status = serializers.ChoiceField(choices=OrderTransaction.PaymentStatus.choices, source="get_payment_status_display")

    class Meta:
        model = OrderTransaction
        fields = ['id','order_purchase', 'transaction_id', 'payment_method', 'amount', 'payment_status', 'payment_date', 'created_at']




class OrderItemSerializer(serializers.ModelSerializer):
    product = ProductDetailWithCategorySerializer(read_only=True)
    delivery_status = serializers.ChoiceField(choices=OrderItem.DeliveryStatus.choices, source="get_delivery_status_display")
    shopping_point = serializers.SerializerMethodField()
    order_review = serializers.SerializerMethodField()
    # product = ProductSerializer(read_only=True)
    # vendor = serializers.CharField(source="vendor.full_name", read_only=True)
    # buyer = serializers.CharField(source="buyer.full_name", read_only=True)
    class Meta:
        model = OrderItem
        fields = ['id', 'order_purchase', 'product', 'buyer', 'vendor', 'product_price', 'origin_product_price', 'quantity', 'color', 'size', 'sub_total', 'total', 'is_shipped', 'is_delivered', 'is_received', 'delivery_status','created_at','delivery_date', 'shopping_point', 'order_review']

    def __init__(self, *args, **kwargs):
        context = kwargs.get('context', {})
        if context.get('is_admin_order_details', False):
            self.fields['buyer'] = UserSerializer(read_only=True) 
            self.fields['vendor'] = UserSerializer(read_only=True) 
        else:
            self.fields['buyer'] = serializers.CharField(source="buyer.full_name", read_only=True)  # All details
            self.fields['vendor'] = serializers.CharField(source="vendor.full_name", read_only=True)  # All details
        
        super().__init__(*args, **kwargs)
    
    def get_shopping_point(self, obj):
        point = ShoppingPoint.objects.filter(
            user=obj.buyer,
            order=obj.order_purchase,
            transaction_type='debit'
        ).first()
        return point.points if point else 0
    
    def get_order_review(self, obj):
        if obj.is_received:
            review_exists = Review.objects.filter(
                product=obj.product,
                user=obj.buyer,
                order_item=obj
            ).exists()

            return not review_exists
        return False



class OrderPurchaseDetailsSerializer(serializers.ModelSerializer):
    # items = OrderItemSerializer(many=True, read_only=True)
    items = serializers.SerializerMethodField()
    transaction = TransactionDetailsSerializer(source='transactions.first', read_only=True) 
    

    class Meta:
        model = OrderPurchase
        fields = [
            'id', 'items', 'total_item_amount', 'tax_percentage', 'total_tax_amount',
            'platform_fee', 'shipping_fee_percentage', 'shipping_fee',
            'free_shipping_amount', 'grand_total', 'payment_status',
            'order_status','transaction', 'shopping_point'
        ]

    def get_items(self, obj):
        request = self.context.get('request')
        order_id = request.query_params.get('order_id') if request else None

        items = obj.items.select_related('product').prefetch_related('product__product_images')
 
        if order_id:
            items = items.exclude(id=int(order_id))  

        return OrderItemSerializer(items, many=True, context=self.context).data

class OrderDetailsSerializer(serializers.ModelSerializer):
    # vendor = UserSerializer(read_only=True)
    # buyer = UserSerializer(read_only=True)
    product = ProductSerializer(read_only=True)
    # transaction = TransactionDetailsSerializer(source='order_purchase.transactions.first', read_only=True)  
    address = serializers.CharField(source='order_purchase.address', read_only=True)
    delivery_status = serializers.ChoiceField(choices=OrderItem.DeliveryStatus.choices, source="get_delivery_status_display")
    order_purchase = OrderPurchaseDetailsSerializer(read_only=True)

    class Meta:
        model = OrderItem
        fields = [
            'id', 'order_purchase', 'product',  'address','quantity', 'color','size',
            'product_price', 'sub_total', 'tax_percentage', 'tax_amount', 'total', 
            # 'is_shipped', 'buyer', 'vendor',
            'is_delivered', 'is_received', 'delivery_status','created_at','delivery_date'
        ]

# Admin Panel Serializers

class OrderListingSerializer(serializers.ModelSerializer) :
    buyer = serializers.CharField(source="buyer.full_name", read_only=True)
    class Meta:
        model = OrderPurchase
        fields = [
            'id', 'buyer', 'grand_total', 'order_date', 'address', 'payment_status','shopping_point' 
            # 'order_status', 'total_item_amount', 'tax_percentage', 'total_tax_amount', 'platform_fee', 'shipping_fee_percentage', 'shipping_fee', 'free_shipping_amount',
            ]
        
class OrderItemTransactionsSerializerOld(OrderItemSerializer):
    transaction = TransactionDetailsSerializer(source='order_purchase.transactions.first', read_only=True)  

    class Meta(OrderItemSerializer.Meta):
        fields = OrderItemSerializer.Meta.fields + ['transaction']

class OrderItemTransactionsSerializer(serializers.ModelSerializer) :

    product = ProductDetailWithCategorySerializer(read_only=True)
    transaction = TransactionDetailsSerializer(source='order_purchase.transactions.first', read_only=True)  

    
    class Meta:
        model = OrderItem
        fields = ['id', 'order_purchase', 'product_price', 'sub_total', 'quantity', 'product', 'color', 'size', 'buyer', 'vendor', 'delivery_status','delivery_date','transaction']

    def __init__(self, *args, **kwargs):
        context = kwargs.get('context', {})
        if context.get('is_admin_order_details', False):
            self.fields['buyer'] = UserSerializer(read_only=True) 
            self.fields['vendor'] = UserSerializer(read_only=True) 
        else:
            self.fields['buyer'] = serializers.CharField(source="buyer.full_name", read_only=True)  # All details
            self.fields['vendor'] = serializers.CharField(source="vendor.full_name", read_only=True)  # All details
        
        super().__init__(*args, **kwargs)


class OrderItemListingSerializer(serializers.ModelSerializer):
    product = ProductDetailWithCategorySerializer(read_only=True)
    delivery_status = serializers.ChoiceField(choices=OrderItem.DeliveryStatus.choices, source="get_delivery_status_display")

    class Meta:
        model = OrderItem
        fields = ['id', 'order_purchase', 'product', 'product_price', 'origin_product_price', 'quantity', 'color', 'size',  'sub_total', 'total', 'is_shipped', 'is_delivered', 'is_received', 'delivery_status','created_at','delivery_date']

    

class AdminOrdeListingSerializer(serializers.ModelSerializer):
    transaction = TransactionDetailsSerializer(source='transactions.first', read_only=True)  
    # order_items = OrderItemListingSerializer(source='items', many=True, context={'is_admin_order_details': True})
    order_items = serializers.SerializerMethodField()
   
    class Meta:
        model = OrderPurchase
        fields = [
            'id', 'order_items', 'transaction', 'address', 'total_item_amount', 'tax_percentage', 'total_tax_amount', 'platform_fee', 'shipping_fee_percentage', 'shipping_fee', 'free_shipping_amount', 'grand_total', 'order_date', 'payment_status', 'order_status',
            'shopping_point'
        ]

    def get_order_items(self, obj):
        item_id = self.context.get('item_id')


        if item_id:
            order_items = obj.items.filter(id=item_id)
            context = {**self.context, 'is_admin_order_details': True} 
        else:
            order_items = obj.items.all()
            context = self.context  # Keep existing context

        return OrderItemSerializer(order_items, many=True, context=context).data


class AdminOrderDetailsSerializer(serializers.ModelSerializer):
    transaction = TransactionDetailsSerializer(source='transactions.first', read_only=True)  
    order_items = OrderItemSerializer(source='items', many=True, context={'is_admin_order_details': True})
   
    class Meta:
        model = OrderPurchase
        fields = [
            'id', 'order_items', 'transaction', 'address', 'total_item_amount', 'tax_percentage', 'total_tax_amount', 'platform_fee', 'shipping_fee_percentage', 'shipping_fee', 'free_shipping_amount', 'grand_total', 'order_date', 'payment_status', 'order_status'
        ]


class VendorOrderItemDetailSerializer(OrderItemListingSerializer):

    transactions = TransactionDetailsSerializer(source='order_purchase.transactions.first', read_only=True)  
    address = serializers.CharField(source='order_purchase.address', read_only=True)
    buyer = UserSerializer(read_only=True)

    class Meta(OrderItemListingSerializer.Meta):
        fields = OrderItemListingSerializer.Meta.fields + ['address', 'buyer', 'transactions']


class VendorOrderItemTransactionsSerializer(serializers.ModelSerializer) :

    product = ProductDetailWithCategorySerializer(read_only=True)
    transaction = TransactionDetailsSerializer(source='order_purchase.transactions.first', read_only=True)  
    buyer = UserSerializer(read_only=True)
    payment_received_date = serializers.CharField(source="delivery_date", read_only=True)
    
    class Meta:
        model = OrderItem
        fields = ['id', 'order_purchase', 'product_price', 'quantity', 'sub_total', 'total', 'product', 'buyer', 'color', 'size', 'payment_received_date', 'transaction']

  