from rest_framework import serializers
from .models import EmailConfig, Notification, NotificationCampaign, NotificationTemplate, UserDeviceToken


class NotificationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Notification
        fields = '__all__'
        read_only_fields = ('status', 'provider', 'sent_at', 'created_at', 'updated_at', 'read_at')


class NotificationTemplateSerializer(serializers.ModelSerializer):
    class Meta:
        model = NotificationTemplate
        fields = '__all__'
        read_only_fields = ('created_at', 'updated_at')


class NotificationCampaignSerializer(serializers.ModelSerializer):
    created_by_name = serializers.SerializerMethodField()
    banner_image_url = serializers.SerializerMethodField()

    class Meta:
        model = NotificationCampaign
        fields = '__all__'
        read_only_fields = (
            'status',
            'sent_at',
            'total_recipients',
            'total_sent',
            'total_failed',
            'created_at',
            'updated_at',
            'created_by_name',
            'banner_image_url',
        )

    def get_created_by_name(self, obj):
        creator = getattr(obj, 'created_by', None)
        if not creator:
            return None
        return (f"{creator.first_name} {creator.last_name}".strip() or creator.mobile or creator.email)

    def get_banner_image_url(self, obj):
        if not obj.banner_image:
            return None
        request = self.context.get('request')
        if request:
            return request.build_absolute_uri(obj.banner_image.url)
        return obj.banner_image.url


class UserDeviceTokenSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserDeviceToken
        fields = ('id', 'platform', 'device_token', 'is_active', 'last_seen_at')
        read_only_fields = ('id', 'last_seen_at')


class EmailConfigSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, required=False, allow_blank=True)
    has_password = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = EmailConfig
        fields = (
            'id',
            'name',
            'provider',
            'host',
            'port',
            'username',
            'password',
            'from_email',
            'use_tls',
            'use_ssl',
            'is_primary',
            'is_enabled',
            'allow_notifications',
            'allow_otps',
            'has_password',
            'created_at',
            'updated_at',
        )
        read_only_fields = ('id', 'has_password', 'created_at', 'updated_at')

    def validate(self, attrs):
        use_tls = attrs.get('use_tls', getattr(self.instance, 'use_tls', True))
        use_ssl = attrs.get('use_ssl', getattr(self.instance, 'use_ssl', False))
        if use_tls and use_ssl:
            raise serializers.ValidationError('Only one of use_tls or use_ssl can be enabled.')
        return attrs

    def create(self, validated_data):
        password = validated_data.pop('password', '')
        email_config = EmailConfig.objects.create(**validated_data)
        if password:
            email_config.password = password
            email_config.save(update_fields=['password', 'updated_at'])
        if email_config.is_primary:
            EmailConfig.objects.exclude(id=email_config.id).update(is_primary=False)
        return email_config

    def update(self, instance, validated_data):
        password = validated_data.pop('password', None)
        for key, value in validated_data.items():
            setattr(instance, key, value)
        if password is not None and password != '':
            instance.password = password
        instance.save()
        if instance.is_primary:
            EmailConfig.objects.exclude(id=instance.id).update(is_primary=False)
        return instance

    def get_has_password(self, obj):
        return bool(obj.password)
