from decimal import Decimal

from rest_framework import serializers

from .models import Services


class ServiceSerializer(serializers.ModelSerializer):
    customers_list = serializers.JSONField()

    class Meta:
        model = Services
        fields = (
            "id",
            "floor",
            "time",
            "total",
            "is_approved",
            "customers_list",
            "year",
            "created_at",
            "updated_at",
        )

    def update(self, instance, validated_data):
        customers_list_data = validated_data.pop("customers_list", None)
        instance.is_approved = validated_data.get("is_approved", instance.is_approved)
        instance.year = validated_data.get("year", instance.year)
        instance.floor = validated_data.get("floor", instance.floor)
        instance.time = validated_data.get("time", instance.time)
        instance.total = Decimal(
            validated_data.get("total", instance.total)
        )  # Ensure total is Decimal

        total_taken = Decimal(0)
        total_remainder = Decimal(0)

        # If customers_list data is provided, update it
        if customers_list_data:
            for customer_id, customer_data in customers_list_data.items():
                if str(customer_id) in instance.customers_list:
                    # If the customer exists in the instance, update their data
                    customer = instance.customers_list[str(customer_id)]

                    # Get 'rant' from the customer data or default to 0 if it's missing
                    rant = Decimal(
                        customer_data.get("rant", 0)
                    )  # Default to 0 if 'rant' is missing
                    taken = Decimal(
                        customer_data.get("taken", customer["taken"])
                    )  # Get 'taken'
                    remainder = rant - taken  # Calculate the remainder (rant - taken)

                    # Update the customer values
                    customer["taken"] = float(taken)  # Store 'taken' as float
                    customer["remainder"] = float(
                        remainder
                    )  # Store 'remainder' as float

                    # Optionally, update 'service' if provided
                    service = Decimal(customer_data.get("service", customer["service"]))
                    customer["service"] = float(service)  # Store 'service' as float

                else:
                    # If the customer is not in the list, add a new entry
                    rant = Decimal(
                        customer_data.get("rant", 0)
                    )  # Default to 0 if 'rant' is missing
                    taken = Decimal(customer_data.get("taken", 0))
                    service = Decimal(customer_data.get("service", 0))
                    remainder = rant - taken  # Calculate the remainder (rant - taken)

                    instance.customers_list[str(customer_id)] = {
                        "taken": float(taken),  # Store 'taken' as float
                        "remainder": float(remainder),  # Store 'remainder' as float
                        "service": float(service),  # Store 'service' as float
                    }

                # Accumulate the 'taken' and 'remainder' values across all customers
                total_taken += taken
                total_remainder += remainder

        # After updating the customer data, update the total fields on the instance
        # NOTE: Do not store total_taken and total_remainder in the instance if you don't want them in the DB
        instance.total_taken = total_taken
        instance.total_remainder = total_remainder

        # Save the instance with the updated fields
        instance.save()
        return instance

    def to_representation(self, instance):
        # Call the parent method to get the default serialized data
        data = super().to_representation(instance)

        # Calculate total_taken and total_remainder dynamically
        total_taken = sum(
            customer["taken"] for customer in data["customers_list"].values()
        )
        total_remainder = sum(
            customer["remainder"] for customer in data["customers_list"].values()
        )

        # Add total_taken and total_remainder to the serialized data
        data["total_taken"] = total_taken
        data["total_remainder"] = total_remainder

        return data
