from rest_framework import serializers
from hub.services.models import ServiceOffering, Plan
from django.utils.html import strip_tags


class ServiceUserSerializer(serializers.Serializer):
    email = serializers.EmailField()
    full_name = serializers.CharField()
    role = serializers.CharField()


class ProvisioningContextSerializer(serializers.Serializer):
    platform = serializers.CharField()
    organization_guid = serializers.CharField()
    space_guid = serializers.CharField()
    organization_name = serializers.CharField()
    organization_display_name = serializers.CharField()


class ProvisioningParametersSerializer(serializers.Serializer):
    users = ServiceUserSerializer(many=True)


class ServiceInstanceProvisioningSerializer(serializers.Serializer):
    service_id = serializers.CharField()  # This will now represent the offering_id
    plan_id = serializers.CharField()
    organization_guid = serializers.CharField()
    space_guid = serializers.CharField()
    parameters = ProvisioningParametersSerializer()
    context = ProvisioningContextSerializer()

    def validate_service_id(self, value):
        """Validate the service_id which now represents the offering_id"""
        try:
            return ServiceOffering.objects.get(pk=value)
        except ServiceOffering.DoesNotExist:
            raise serializers.ValidationError("Invalid offering_id")

    def validate_plan_id(self, value):
        try:
            # Get the plan and ensure it belongs to the selected offering
            plan = Plan.objects.get(pk=value)
            offering = self.initial_data.get("service_id")
            if str(plan.offering.id) != offering:
                raise serializers.ValidationError(
                    "Plan does not belong to the selected offering"
                )
            return plan
        except Plan.DoesNotExist:
            raise serializers.ValidationError("Invalid plan_id")


class CostSerializer(serializers.Serializer):
    amount = serializers.DecimalField(max_digits=10, decimal_places=2)
    unit = serializers.CharField()


class PlanMetadataSerializer(serializers.Serializer):
    bullets = serializers.ListField(child=serializers.CharField(), required=False)
    costs = CostSerializer(many=True, required=False)


class PlanSerializer(serializers.ModelSerializer):
    id = serializers.SerializerMethodField()
    description = serializers.SerializerMethodField()
    free = serializers.SerializerMethodField()
    bindable = serializers.SerializerMethodField()

    def get_id(self, obj):
        return str(obj.pk)

    def get_description(self, obj):
        return strip_tags(obj.description) if obj.description else ""

    def get_free(self, obj):
        return False

    def get_bindable(self, obj):
        return False

    class Meta:
        model = Plan
        fields = ["id", "name", "description", "free", "bindable"]


class ServiceOfferingMetadataSerializer(serializers.Serializer):
    displayName = serializers.CharField()
    providerDisplayName = serializers.CharField()
    longDescription = serializers.SerializerMethodField()
    imageUrl = serializers.URLField(required=False)

    def get_longDescription(self, obj):
        return strip_tags(obj["longDescription"]) if obj.get("longDescription") else ""


class ServiceOfferingSerializer(serializers.ModelSerializer):
    id = serializers.SerializerMethodField()
    name = serializers.SerializerMethodField()
    description = serializers.SerializerMethodField()
    plans = PlanSerializer(many=True)
    bindable = serializers.BooleanField(default=True)
    metadata = serializers.SerializerMethodField()

    class Meta:
        model = ServiceOffering
        fields = ["id", "name", "description", "plans", "bindable", "metadata"]

    def get_id(self, obj):
        return str(obj.pk)

    def get_name(self, obj):
        return f"{obj.service.name}-{obj.cloud_provider.name}".lower().replace(" ", "-")

    def get_description(self, obj):
        return strip_tags(obj.description) if obj.description else ""

    def get_metadata(self, obj):
        return ServiceOfferingMetadataSerializer(
            {
                "displayName": obj.service.name,
                "providerDisplayName": obj.cloud_provider.name,
                "longDescription": obj.description,
                "imageUrl": obj.service.logo.url if obj.service.logo else None,
            }
        ).data


class CatalogSerializer(serializers.Serializer):
    services = ServiceOfferingSerializer(many=True)


class ServiceInstanceUpdateSerializer(serializers.Serializer):
    plan_id = serializers.CharField()

    def validate_plan_id(self, value):
        try:
            plan = Plan.objects.get(pk=value)
            # Get instance from context
            instance = self.context.get("instance")
            if str(plan.offering.id) != str(instance.offering.id):
                raise serializers.ValidationError(
                    "Plan does not belong to the current offering"
                )
            return plan
        except Plan.DoesNotExist:
            raise serializers.ValidationError("Invalid plan_id")
