from decimal import Decimal

from rest_framework import serializers

from apps.agreement.models import Agreement

from .models import Rant


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

    class Meta:
        model = Rant
        fields = (
            "id",
            "floor",
            "time",
            "year",
            "total",
            "customers_list",
        )

    def get_customers_list(self, obj):
        active_agreements = Agreement.objects.filter(status="Active", floor=obj.floor)

        customers_data = {}
        total_rent = Decimal("0.00")

        # Create customer data for each active agreement
        for agreement in active_agreements:
            customer_id = str(agreement.customer.id)
            customer_data = {
                "rant": float(agreement.rant),  # Convert 'rant' to float for response
                "taken": float(0),  # Default 'taken' value is 0
                "remainder": float(0),  # Default 'remainder' value is 0
            }
            customers_data[customer_id] = customer_data
            total_rent += agreement.rant

        obj.total = total_rent
        obj.save()

        return customers_data

    def update(self, instance, validated_data):
        # Update the other fields
        instance.floor = validated_data.get("floor", instance.floor)
        instance.time = validated_data.get("time", instance.time)
        instance.year = validated_data.get("year", instance.year)

        # Get the provided customers list from the patch request
        customers_data = validated_data.get("customers_list", None)

        if customers_data:
            # Iterate through the provided customer data and update the list
            for customer_id, customer_data in customers_data.items():
                if str(customer_id) in instance.customers_list:
                    # Update the existing customer data
                    customer = instance.customers_list[str(customer_id)]

                    # Update rant, taken, and calculate the remainder
                    rant = float(customer_data.get("rant", customer.get("rant", 0)))
                    taken = float(customer_data.get("taken", customer.get("taken", 0)))
                    remainder = rant - taken  # Calculate the remainder

                    customer["rant"] = rant
                    customer["taken"] = taken
                    customer["remainder"] = remainder  # Set the calculated remainder
                else:
                    # If the customer doesn't exist in the list, add them
                    rant = float(customer_data.get("rant", 0))
                    taken = float(customer_data.get("taken", 0))
                    remainder = rant - taken  # Calculate the remainder

                    instance.customers_list[str(customer_id)] = {
                        "rant": rant,
                        "taken": taken,
                        "remainder": remainder,  # Add the calculated remainder
                    }

            # Recalculate the total after modifying the customers' data
            instance.total = sum(
                float(
                    customer.get("rant", 0)
                )  # Use .get() to safely handle missing 'rant'
                for customer in instance.customers_list.values()
            )

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

    def to_representation(self, instance):
        data = super().to_representation(instance)

        # Calculate total_taken and total_remainder
        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
