from rest_framework import serializers
from shop_management.models.data.purchase_return import PurchaseReturn, PurchaseReturnItem
from shop_management.serializers.data.purchase import PurchaseSerializer, PurchaseItemSerializer
from shop_management.serializers.data.shop import ShopSerializer
from shop_management.serializers.data.base import DataRootSerializer
from account.permissions import assert_shop_access


class PurchaseReturnItemSerializer(serializers.ModelSerializer):
    purchase_item_details = PurchaseItemSerializer(source='purchase_item', read_only=True)
    
    class Meta:
        model = PurchaseReturnItem
        fields = ['id', 'purchase_item', 'batch', 'return_quantity', 'refund_amount', 'created_at', 'purchase_item_details']
        read_only_fields = ['id', 'created_at']


class PurchaseReturnSerializer(DataRootSerializer):
    return_items = PurchaseReturnItemSerializer(many=True)
    purchase_details = PurchaseSerializer(source='purchase', read_only=True)
    shop_details = ShopSerializer(source='shop', read_only=True)
    total_refund_amount = serializers.ReadOnlyField()
    
    class Meta:
        model = PurchaseReturn
        fields = ['id', 'purchase', 'shop', 'return_date', 'reason', 'return_items',
                 'purchase_details', 'shop_details', 'total_refund_amount', 'return_number',
                 'document_status', 'uses_inventory_engine', 'posted_at', 'posted_by',
                 'voided_at', 'voided_by', 'void_reason', 'created_at', 'updated_at']
        read_only_fields = ['id', 'return_date', 'return_number', 'document_status',
                            'uses_inventory_engine', 'posted_at', 'posted_by', 'voided_at',
                            'voided_by', 'void_reason', 'created_at', 'updated_at']

    def validate(self, attrs):
        shop = attrs.get("shop") or getattr(self.instance, "shop", None)
        purchase = attrs.get("purchase") or getattr(self.instance, "purchase", None)
        request = self.context.get("request")
        if request and shop:
            shop = assert_shop_access(request.user, shop, request)
        if shop and purchase and purchase.shop_id != shop.pk:
            raise serializers.ValidationError({"purchase": "Purchase must belong to the selected branch."})
        if (
            purchase
            and purchase.uses_inventory_engine
            and purchase.document_status != purchase.DocumentStatus.POSTED
        ):
            raise serializers.ValidationError({"purchase": "Only posted purchases can be returned."})
        return attrs

    def create(self, validated_data):
        return_items_data = validated_data.pop('return_items')
        request = self.context.get("request")
        created_by = request.user if request and request.user.is_authenticated else None
        if created_by and "created_by" not in validated_data:
            validated_data["created_by"] = created_by
        purchase_return = PurchaseReturn.objects.create(**validated_data)
        
        for item_data in return_items_data:
            if created_by and "created_by" not in item_data:
                item_data["created_by"] = created_by
            PurchaseReturnItem.objects.create(purchase_return=purchase_return, **item_data)
        
        return purchase_return

    def update(self, instance, validated_data):
        return_items_data = validated_data.pop('return_items', [])
        
        # Update purchase return fields
        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()
        
        # Update return items
        if return_items_data:
            request = self.context.get("request")
            created_by = request.user if request and request.user.is_authenticated else instance.created_by
            instance.return_items.all().delete()
            for item_data in return_items_data:
                if created_by and "created_by" not in item_data:
                    item_data["created_by"] = created_by
                PurchaseReturnItem.objects.create(purchase_return=instance, **item_data)
        
        return instance
