from rest_framework import serializers
from .models import *
from v1.serializers import TypeSerializer, PropertiesNestedSimpleSerializer, AgentSerializer, OfficeSerializer, FeatureSerializer, PropertiesNestedSerializer, StateSimpleSerializer, CitySimpleSerializer, NeighborhoodSimpleSerializer
from v1.models import Types, PropertiesNested, Agents, Offices, Features, State, City, Neighborhood
from accounts.serializers import UsuarioSimpleSerializer
from decimal import Decimal
from decimal import InvalidOperation
from django.contrib.auth import get_user_model
from datetime import datetime
from bson import ObjectId
import json
import os
from django.conf import settings
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from collections import OrderedDict
from django.utils import timezone
from .utils import handle_uploaded_file

Usuario = get_user_model()

# Create a logger'
import logging
logger = logging.getLogger('panel.serializers')
# Set the logger level to DEBUG (or INFO, depending on your preference)
logger.setLevel(logging.DEBUG)

# Define the file path
logging_file = os.path.join(settings.LOGGING_FILE_ROOT, 'panel_serializers.log')

# Create a file handler specific for this logger
file_handler = logging.FileHandler(logging_file)
file_handler.setLevel(logging.DEBUG)

# Create a logging format
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)

# Add the file handler to the logger
if not logger.handlers:
    logger.addHandler(file_handler)
    
#logger.info("Logger initialized for panel.serializers")

### Favorito

# class FavoritoReadOnlySerializer(serializers.ModelSerializer):
    
#     cliente = UsuarioSimpleSerializer(many=True, read_only=True)
#     tipo_imovel = TypeSerializer(many=True, read_only=True)
#     imovel = PropertiesNestedSerializer(many=True, read_only=True)
    
#     class Meta:
#         model = Favorito
#         fields = '__all__'
#         extra_kwargs = {
#             'cliente': {'required': True},
# 			'tipo_imovel': {'required': True},
# 			'imovel': {'required': True}
# 		}


# class FavoritoWriteOnlySerializer(serializers.ModelSerializer):
#     cliente = serializers.CharField()
#     tipo_imovel = serializers.CharField()
#     imovel = serializers.CharField()
    
#     class Meta:
#         model = Favorito
#         fields = '__all__'
#         extra_kwargs = {
# 			'cliente': {'required': True},
# 			'tipo_imovel': {'required': True},
# 			'imovel': {'required': True},
# 		}
    
#     def validate(self, attrs):
#         #print(f"Validate Attrs: {attrs}")
#         if 'cliente' not in attrs:
#             raise serializers.ValidationError("Cliente is required.")
#         elif 'tipo_imovel' not in attrs:
#             raise serializers.ValidationError("Tipo Imovel is required.")
#         elif 'imovel' not in attrs:
#             raise serializers.ValidationError("Imovel is required.")
#         else:
#             if not Usuario.objects.get(id=ObjectId(attrs['cliente']), categoria='cliente'):
#                 raise serializers.ValidationError("Cliente not found.")
#             elif not Types.objects.get(type_id=int(attrs['tipo_imovel'])):
#                 raise serializers.ValidationError("Tipo Imovel not found.")
#             elif not PropertiesNested.objects.get(property_id=int(attrs['imovel'])):
#                 raise serializers.ValidationError("Imovel not found.")
#         return super().validate(attrs)
    
#     def create(self, validated_data):

#         validated_data['cliente_id'] = [ObjectId(validated_data.pop('cliente'))]
#         validated_data['tipo_imovel_id'] = [int(validated_data.pop('tipo_imovel'))]
#         validated_data['imovel_id'] = [int(validated_data.pop('imovel'))]

#         obj_id = self.Meta.model.objects.mongo_insert(validated_data)
#         obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

#         obj_data['id'] = obj_data.pop('_id')
#         obj_data['cliente'] = obj_data.pop('cliente_id')
#         obj_data['tipo_imovel'] = obj_data.pop('tipo_imovel_id')
#         obj_data['imovel'] = obj_data.pop('imovel_id')
        
#         obj = self.Meta.model(**obj_data)
        
#         return obj

#     def update(self, instance, validated_data):
#         ### Cliente ###
#         if 'cliente' in validated_data:
#             validated_data['cliente_id'] = [ObjectId(validated_data.pop('cliente', []))]
#         ### Tipo Imovel ###
#         if 'tipo_imovel' in validated_data:
#             validated_data['tipo_imovel_id'] = [int(validated_data.pop('tipo_imovel', []))]
#         ### Imovel ###
#         if 'imovel' in validated_data:
#             validated_data['imovel_id'] = [int(validated_data.pop('imovel', []))]
            

#         obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
#         if obj:
#             return instance
#         else:
#             return None

from accounts.models import Cliente
from accounts.serializers import ClienteSerializer


class FavoritoAddSerializer(serializers.ModelSerializer):
    tipo_imovel_id = serializers.IntegerField(required=True)
    imovel_id = serializers.IntegerField(required=True)
    
    class Meta:
        model = Favorito
        fields = ['tipo_imovel_id', 'imovel_id']
        
class FavoritoDeleteSerializer(serializers.ModelSerializer):
    pass
    
    class Meta:
        model = Favorito
        exclude = ['tipo_imovel', 'imovel', 'cliente', 'id']


class FavoritoSerializer(serializers.ModelSerializer):
    tipo_imovel = TypeSerializer(many=True, read_only=True)
    imovel = PropertiesNestedSimpleSerializer(many=True, read_only=True)
    cliente = ClienteSerializer(many=True, read_only=True)
    tipo_imovel_id = serializers.IntegerField(write_only=True, required=True)
    imovel_id = serializers.IntegerField(write_only=True, required=True)
    cliente_id = serializers.CharField(write_only=True, required=True)
    
    class Meta:
        model = Favorito
        fields = '__all__'
        extra_kwargs = {
            'tipo_imovel': {'required': False},
			'imovel': {'required': False},
			'cliente': {'required': False},
		}
    
    def validate(self, attrs):
        #print(f"Validate Attrs: {attrs}")
        if 'cliente_id' not in attrs and self.instance is None:
            raise serializers.ValidationError("Cliente is required.")
        elif 'tipo_imovel_id' not in attrs and self.instance is None:
            raise serializers.ValidationError("Tipo Imovel is required.")
        elif 'imovel_id' not in attrs and self.instance is None:
            raise serializers.ValidationError("Imovel is required.")
        else:
            if 'cliente_id' in attrs and not Cliente.objects.get(id=ObjectId(attrs['cliente_id'])):
                raise serializers.ValidationError("Cliente not found.")
            elif 'tipo_imovel_id' in attrs and not Types.objects.get(type_id=int(attrs['tipo_imovel_id'])):
                raise serializers.ValidationError("Tipo Imovel not found.")
            elif 'imovel_id' in attrs and not PropertiesNested.objects.get(property_id=int(attrs['imovel_id'])):
                raise serializers.ValidationError("Imovel not found.")
        return super().validate(attrs)
    
    def create(self, validated_data):
        # Extract IDs from validated data
        tipo_imovel_id = validated_data.pop("tipo_imovel_id")
        imovel_id = validated_data.pop("imovel_id")
        cliente_id = validated_data.pop("cliente_id")
        
        validated_data['tipo_imovel_id'] = [int(tipo_imovel_id)]
        validated_data['imovel_id'] = [int(imovel_id)]
        validated_data['cliente_id'] = [ObjectId(cliente_id)]

        # ✅ Create the object with proper ForeignKey instances
        favorito = Favorito.objects.create(**validated_data)
        return favorito



    def update(self, instance, validated_data):
        """ Update ContatoCliente instance with ForeignKey fields properly. """

        # 🔎 Check if related fields need to be updated
        if "tipo_imovel_id" in validated_data:
            validated_data["tipo_imovel_id"] = [int(validated_data.pop("tipo_imovel_id"))]
        if "imovel_id" in validated_data:
            validated_data["imovel_id"] = [int(validated_data.pop("imovel_id"))]
        if "cliente_id" in validated_data:
            validated_data["cliente_id"] = [ObjectId(validated_data.pop("cliente_id"))]

        # ✅ Call the parent `update` method
        return super().update(instance, validated_data)
    

class ContatoClienteAddSerializer(serializers.ModelSerializer):
    tipo_imovel_id = serializers.IntegerField(required=False)
    imovel_id = serializers.IntegerField(required=False)
    mensagem = serializers.CharField(required=True)
    
    class Meta:
        model = ContatoCliente
        fields = ['tipo_imovel_id', 'imovel_id', 'mensagem']

class ContatoClienteDeleteSerializer(serializers.ModelSerializer):
    pass
    
    class Meta:
        model = ContatoCliente
        exclude = ['tipo_imovel', 'imovel', 'cliente', 'mensagem','id']


class ContatoClienteSerializer(serializers.ModelSerializer):
    tipo_imovel = TypeSerializer(many=True, read_only=True)
    imovel = PropertiesNestedSimpleSerializer(many=True, read_only=True)
    cliente = ClienteSerializer(many=True, read_only=True)
    tipo_imovel_id = serializers.IntegerField(write_only=True, required=True)
    imovel_id = serializers.IntegerField(write_only=True, required=True)
    cliente_id = serializers.CharField(write_only=True, required=True)
    mensagem = serializers.CharField(required=True) 
    
    class Meta:
        model = ContatoCliente
        fields = '__all__'
        extra_kwargs = {
            'tipo_imovel': {'required': False},
			'imovel': {'required': False},
			'cliente': {'required': False},
			'mensagem': {'required': True},
		}
    
    def validate(self, attrs):
        #print(f"Validate Attrs: {attrs}")
        if 'cliente_id' not in attrs and self.instance is None:
            raise serializers.ValidationError("Cliente is required.")
        elif 'tipo_imovel_id' not in attrs and self.instance is None:
            raise serializers.ValidationError("Tipo Imovel is required.")
        elif 'imovel_id' not in attrs and self.instance is None:
            raise serializers.ValidationError("Imovel is required.")
        else:
            if 'cliente_id' in attrs and not Cliente.objects.get(id=ObjectId(attrs['cliente_id'])):
                raise serializers.ValidationError("Cliente not found.")
            elif 'tipo_imovel_id' in attrs and not Types.objects.get(type_id=int(attrs['tipo_imovel_id'])):
                raise serializers.ValidationError("Tipo Imovel not found.")
            elif 'imovel_id' in attrs and not PropertiesNested.objects.get(property_id=int(attrs['imovel_id'])):
                raise serializers.ValidationError("Imovel not found.")
        return super().validate(attrs)
    
    def create(self, validated_data):
        # Extract IDs from validated data
        tipo_imovel_id = validated_data.pop("tipo_imovel_id")
        imovel_id = validated_data.pop("imovel_id")
        cliente_id = validated_data.pop("cliente_id")
        
        validated_data['tipo_imovel_id'] = [int(tipo_imovel_id)]
        validated_data['imovel_id'] = [int(imovel_id)]
        validated_data['cliente_id'] = [ObjectId(cliente_id)]

        # ✅ Create the object with proper ForeignKey instances
        contato_cliente = ContatoCliente.objects.create(**validated_data)
        return contato_cliente



    def update(self, instance, validated_data):
        """ Update ContatoCliente instance with ForeignKey fields properly. """

        # 🔎 Check if related fields need to be updated
        if "tipo_imovel_id" in validated_data:
            validated_data["tipo_imovel_id"] = [int(validated_data.pop("tipo_imovel_id"))]
        if "imovel_id" in validated_data:
            validated_data["imovel_id"] = [int(validated_data.pop("imovel_id"))]
        if "cliente_id" in validated_data:
            validated_data["cliente_id"] = [ObjectId(validated_data.pop("cliente_id"))]

        # ✅ Call the parent `update` method
        return super().update(instance, validated_data)

        
        
class ContatoClienteReadOnlySerializer(serializers.ModelSerializer):
    
    tipo_imovel = TypeSerializer(many=True, read_only=True)
    imovel = PropertiesNestedSimpleSerializer(many=True, read_only=True)
    cliente = ClienteSerializer(many=True, read_only=True)

    
    class Meta:
        model = ContatoCliente
        fields = '__all__'
        extra_kwargs = {
            'tipo_imovel': {'required': True},
			'imovel': {'required': True},
			'cliente': {'required': True},
			'mensagem': {'required': True},
		}


        
from accounts.models import Cliente
class ContatoClienteWriteOnlySerializer(serializers.ModelSerializer):
    
    tipo_imovel = serializers.CharField()
    imovel = serializers.CharField()
    cliente = serializers.CharField()
    
    class Meta:
        model = ContatoCliente
        fields = '__all__'
        extra_kwargs = {
            'tipo_imovel': {'required': True},
			'imovel': {'required': True},
			'cliente': {'required': True},
			'mensagem': {'required': True},
		}
        
    def validate(self, attrs):
        print(f"Validate Attrs: {attrs}")
        if 'cliente' not in attrs:
            raise serializers.ValidationError("Cliente is required.")
        elif 'tipo_imovel' not in attrs:
            raise serializers.ValidationError("Tipo Imovel is required.")
        elif 'imovel' not in attrs:
            raise serializers.ValidationError("Imovel is required.")
        else:
            if not Cliente.objects.get(id=ObjectId(attrs['cliente'])):
                raise serializers.ValidationError("Cliente not found.")
            elif not Types.objects.get(type_id=int(attrs['tipo_imovel'])):
                raise serializers.ValidationError("Tipo Imovel not found.")
            elif not PropertiesNested.objects.get(property_id=int(attrs['imovel'])):
                raise serializers.ValidationError("Imovel not found.")
        return super().validate(attrs)
    
    def create(self, validated_data):

        validated_data['cliente_id'] = [ObjectId(validated_data.pop('cliente'))]
        validated_data['tipo_imovel_id'] = [int(validated_data.pop('tipo_imovel'))]
        validated_data['imovel_id'] = [int(validated_data.pop('imovel'))]

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj_data['cliente'] = obj_data.pop('cliente_id')
        obj_data['tipo_imovel'] = obj_data.pop('tipo_imovel_id')
        obj_data['imovel'] = obj_data.pop('imovel_id')
        
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
        
        return obj
    


    def update(self, instance, validated_data):
        ### Cliente ###
        if 'cliente' in validated_data:
            validated_data['cliente_id'] = [ObjectId(validated_data.pop('cliente', []))]
        ### Tipo Imovel ###
        if 'tipo_imovel' in validated_data:
            validated_data['tipo_imovel_id'] = [int(validated_data.pop('tipo_imovel', []))]
        ### Imovel ###
        if 'imovel' in validated_data:
            validated_data['imovel_id'] = [int(validated_data.pop('imovel', []))]
            

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            return instance
        else:
            return None
        

class CategoriaSerializer(serializers.ModelSerializer):
    
    imagem = serializers.CharField()
    
    class Meta:
        model = Categoria
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': False},
            'nome': {'required': True},
            'descricao': {'required': False},
            'resumo': {'required': False},
            'name': {'required': False},
            'description': {'required': False},
            'summary': {'required': False},
            'imagem': {'required': False},
        }

    def create(self, validated_data):
        # Handle the `ordem` field logic during creation
        if 'ordem' not in validated_data or validated_data['ordem'] is None:
            # If no `ordem` is provided, gets the last ordem and increments by 1
            last_ordem = Categoria.objects.order_by('-ordem').first()
            validated_data['ordem'] = last_ordem.ordem + 1 if last_ordem else 1
            # Increment the `ordem` of all existing categories
            # categorias_to_update = Categoria.objects.all()
            # for categoria in categorias_to_update:
            #     categoria.ordem += 1
            #     categoria.save()
        else:
            # If `ordem` is provided, increment the `ordem` of categories with equal or greater `ordem`
            ordem = validated_data['ordem']
            categorias_to_update = Categoria.objects.filter(ordem__gte=ordem)
            for categoria in categorias_to_update:
                categoria.ordem += 1
                categoria.save()

        return super().create(validated_data)

    def update(self, instance, validated_data):
        # Handle the `ordem` field logic during update
        new_ordem = validated_data.get('ordem', instance.ordem)
        if new_ordem != instance.ordem:
            if new_ordem > instance.ordem:
                # Moving the category down in the order
                categorias_to_update = Categoria.objects.filter(ordem__gt=instance.ordem, ordem__lte=new_ordem)
                for categoria in categorias_to_update:
                    categoria.ordem -= 1
                    categoria.save()
            else:
                # Moving the category up in the order
                categorias_to_update = Categoria.objects.filter(ordem__lt=instance.ordem, ordem__gte=new_ordem)
                for categoria in categorias_to_update:
                    categoria.ordem += 1
                    categoria.save()
            validated_data['ordem'] = new_ordem

        return super().update(instance, validated_data)
    

class PostReadOnlySerializer(serializers.ModelSerializer):
    
    categorias = CategoriaSerializer(many=True, read_only=True)
    autor = UsuarioSimpleSerializer(many=True, read_only=True)
    
    class Meta:
        model = Post
        fields = '__all__'
        extra_kwargs = {
            'data': {'required': False},
			'titulo': {'required': True},
            'subtitulo': {'required': False},
			'conteudo': {'required': True},
			'imagem_principal': {'required': True},
			'tags': {'required': False},
			'categorias': {'required': True},
			'autor': {'required': True},
            'slug': {'required': False},
		}
        
class PostWriteOnlySerializer(serializers.ModelSerializer):
    
    categorias = serializers.CharField()
    autor = serializers.CharField()
    imagem_principal = serializers.CharField()
    data = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", input_formats=["%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%d"])
    #tags = serializers.ListField(child=serializers.CharField())
    tags = serializers.CharField()
    
    class Meta:
        model = Post
        fields = '__all__'
        extra_kwargs = {
            'data': {'required': False},
            'titulo': {'required': True},
            'subtitulo': {'required': False, 'allow_null': True},
            'conteudo': {'required': True},
            'imagem_principal': {'required': True},
            'tags': {'required': False},
            'categorias': {'required': True},
            'autor': {'required': True},
            'slug': {'required': False},
        }
    
    def validate(self, attrs):
        if 'categorias' not in attrs and self.instance is None:
            raise serializers.ValidationError("'Categorias' is required.")
        if 'autor' not in attrs and self.instance is None:
            raise serializers.ValidationError("Autor is required.")
        
        if 'autor' in attrs:
            autor = Usuario.objects.get(id=ObjectId(attrs['autor']))
            if not autor:
                raise serializers.ValidationError("Autor not found.")
        
        if 'categorias' in attrs:
            categorias = str(attrs['categorias']).replace('[', '').replace(']', '').replace('\'', '').split(',')
            pipeline = [
                {'$match': {'_id': {'$in': [ObjectId(cat) for cat in categorias]}}}
            ]
            qtd_categorias_found = len(list(Categoria.objects.mongo_aggregate(pipeline)))
            if len(categorias) != qtd_categorias_found:
                raise serializers.ValidationError("CategoriaS not found.")
        
        if 'tags' in attrs:
            tags = attrs['tags']
            if isinstance(tags, str):
                try:
                    #print("Trying to load tags as JSON")
                    tags = json.loads(tags)
                    attrs['tags'] = tags
                except json.JSONDecodeError:
                    # If it fails, split by commas to handle form-data strings
                    tags = tags.split(',')
                    attrs['tags'] = tags
            
            # Ensure that value is now a list of strings
            if not all(isinstance(tag, str) for tag in tags):
                raise serializers.ValidationError("Tags must be a list of strings.")
                

        return super().validate(attrs)


    
    def create(self, validated_data):
       # Ensure tags are present and processed correctly
        validated_data['tags'] = validated_data.get('tags', [])
        #print(f"tags create before: {validated_data['tags']}")
        #print(type(validated_data['tags']))
        
        if isinstance(validated_data['tags'], list):
            ## eliminate any empty strings
            validated_data['tags'] = [tag for tag in validated_data['tags'] if tag]
        else:
            validated_data['tags'] = [tag for tag in validated_data['tags'].split(',') if tag]

        validated_data['tags'] = [tag.strip('"').strip("'") for tag in validated_data['tags']]
        #print(f"tags create after: {validated_data['tags']}")
        

        # for tag in validated_data['tags']:
        #     print(f"Tag: {tag}")
        
        # Ensure 'data' is a datetime.datetime object
        if not validated_data['data']:
            validated_data['data'] = datetime.now()

        # Set 'data_cadastro' to the current datetime
        validated_data['data_cadastro'] = datetime.now()

        # Convert the autor and categorias fields to ObjectId
        validated_data['autor_id'] = [ObjectId(validated_data.pop('autor'))]
        categorias = str(validated_data.pop('categorias')).replace('[', '').replace(']', '').replace('\'', '').split(',')
        validated_data['categorias_id'] = [ObjectId(cat) for cat in categorias]

        #print(validated_data)
        #exit()
        # Insert the data into MongoDB
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        # Prepare data for the Post instance
        obj_data['id'] = obj_data.pop('_id')
        obj_data['autor'] = obj_data.pop('autor_id')
        obj_data['categorias'] = obj_data.pop('categorias_id')

        # Create and return the Post instance
        obj = self.Meta.model(**obj_data)
        return obj

    def update(self, instance, validated_data):
        # Set 'data_atualizacao' to the current datetime
        validated_data['data_atualizacao'] = datetime.now()

        # Ensure 'data' is a datetime.datetime object
        validated_data['data'] = validated_data.get('data', instance.data)

        # Handle autor and categorias updates
        if 'autor' in validated_data:
            validated_data['autor_id'] = [ObjectId(validated_data.pop('autor'))]
        
        if 'categorias' in validated_data:
            categorias = str(validated_data.pop('categorias')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['categorias_id'] = [ObjectId(cat) for cat in categorias]

        # Update the MongoDB document
        self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': validated_data})
        return instance
    


class BannerMosaicosReadOnlySerializer(serializers.ModelSerializer):
    
    posts = PostReadOnlySerializer(many=True, read_only=True)
    
    class Meta:
        model = BannerMosaico
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': True},
			'template': {'required': True},
			'posts': {'required': True},
		}
        
class BannerMosaicosWriteOnlySerializer(serializers.ModelSerializer):
    
    posts = serializers.CharField()
    template = serializers.CharField()
    
    class Meta:
        model = BannerMosaico
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': True},
			'template': {'required': False},
			'posts': {'required': True},
		}

    def validate(self, attrs):
        if 'posts' not in attrs:
            raise serializers.ValidationError("'Posts' is required.")
        else:
            posts = str(attrs['posts']).replace('[', '').replace(']', '').replace('\'', '').split(',')
            pipeline = [
                {'$match': {'_id': {'$in': [ObjectId(post) for post in posts]}}}
            ]
            qtd_posts_found = len(list(Post.objects.mongo_aggregate(pipeline)))
            if len(posts) != qtd_posts_found:
                raise serializers.ValidationError("Posts not found.")
        return super().validate(attrs)
    
    def create(self, validated_data):

        validated_data['posts'] = str(validated_data.pop('posts')).replace('[', '').replace(']', '').replace('\'', '').split(',')
        validated_data['posts_id'] = [ObjectId(post) for post in validated_data.pop('posts')]

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj_data['posts'] = obj_data.pop('posts_id')
  
        
        obj = self.Meta.model(**obj_data)
        
        return obj

    def update(self, instance, validated_data):
            
        if 'posts' in validated_data:
            posts = str(validated_data.pop('posts')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['posts_id'] = [ObjectId(post) for post in posts]

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            return instance
        else:
            return None


class SimulacaoSerializer(serializers.ModelSerializer):
    
    valor_maximo_parcelas = serializers.DecimalField(max_digits=10, decimal_places=2, required=False)
    renda_familiar_mensal = serializers.DecimalField(max_digits=10, decimal_places=2, required=False)
    entrada_disponivel = serializers.DecimalField(max_digits=10, decimal_places=2, required=False)
    fgts = serializers.DecimalField(max_digits=10, decimal_places=2, required=False)
    
    class Meta:
        model = Simulacao
        fields = '__all__'
        extra_kwargs = {
            'tipo': {'required': True},
			'entrada_disponivel': {'required': True},
			'nome': {'required': True},
			'email': {'required': True},
			'telefone': {'required': True},
		}
    
    def validate(self, attrs):
        #print(f"Data: {attrs}")
        
        if 'tipo' in attrs:
            if attrs['tipo'] not in ['renda_familiar', 'valor_parcelas']:
                raise serializers.ValidationError("Tipo must be 'renda_familiar' or 'valor_parcelas'.")
            elif attrs['tipo'] == 'renda_familiar' and 'renda_familiar_mensal' not in attrs:
                raise serializers.ValidationError("Renda familiar mensal is required for 'renda_familiar' type.")
            elif attrs['tipo'] == 'valor_parcelas' and 'valor_maximo_parcelas' not in attrs:
                raise serializers.ValidationError("Valor máximo de parcelas is required for 'valor_parcelas' type.")
        
        # Convert string representations of decimal fields to Decimal
        for field in ['renda_familiar_mensal', 'valor_maximo_parcelas', 'entrada_disponivel', 'fgts']:
            if field in attrs and isinstance(attrs[field], str):
                try:
                    attrs[field] = Decimal(attrs[field])
                except InvalidOperation:
                    raise serializers.ValidationError({field: "Value must be a decimal number."})
        
        return super().validate(attrs)
    
    
    def create(self, validated_data):
        # Convert Decimal fields to float before saving
        for field in ['renda_familiar_mensal', 'valor_maximo_parcelas', 'entrada_disponivel', 'fgts']:
            if field in validated_data:
                validated_data[field] = float(validated_data[field])
        
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj = self.Meta.model(**obj_data)
        return obj
    
    
    def update(self, instance, validated_data):

        # Convert Decimal fields to float before saving
        for field in ['renda_familiar_mensal', 'valor_maximo_parcelas', 'entrada_disponivel', 'fgts']:
            if field in validated_data:
                validated_data[field] = float(validated_data[field])
        
        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            return instance
        else:
            return None


class AssuntoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Assunto
        fields = '__all__'
        extra_kwargs = {
            'nome': {'required': True},
			'email': {'required': True},
		}
        
        
class ContatoReadOnlySerializer(serializers.ModelSerializer):
    assunto = AssuntoSerializer(many=True, read_only=True)
    imovel = PropertiesNestedSimpleSerializer(many=True, read_only=True)
    cliente = ClienteSerializer(many=True, read_only=True)
    
    class Meta:	
        model = Contato
        fields = '__all__'
        extra_kwargs = {
            'nome': {'required': True},
            'email': {'required': True},
            'telefone': {'required': True},
            'estado': {'required': True},
            'cidade': {'required': True},
            'mensagem': {'required': True},
            'assunto': {'required': False},
            'rastreamento': {'default': []},
            'news': {'default': False},
            'whatsapp': {'default': False},
            'imovel': {'required': False},
            'cliente': {'required': False},
            'tipo': {'default': 'mensagem'},
        }
        


class ContatoWriteOnlySerializer(serializers.ModelSerializer):
    assunto = serializers.CharField(required=False)
    imovel = serializers.CharField(required=False)
    cliente = serializers.CharField(required=False)

    class Meta:	
        model = Contato
        fields = '__all__'
        extra_kwargs = {
            'nome': {'required': True},
            'email': {'required': True},
            'telefone': {'required': True},
            'estado': {'required': True},
            'cidade': {'required': True},
            'mensagem': {'required': True},
            'assunto': {'required': False},
            'rastreamento': {'default': []},
            'news': {'default': False},
            'whatsapp': {'default': False},
            'imovel': {'required': False},
            'cliente': {'required': False},
            'tipo': {'default': 'mensagem'},
        }
    

    def validate(self, attrs):
        if 'assunto' in attrs:
            assunto = Assunto.objects.get(id=ObjectId(attrs['assunto']))
            if not assunto:
                raise serializers.ValidationError("Assunto not found.")
            
        if 'cliente' in attrs and not Cliente.objects.get(id=ObjectId(attrs['cliente'])):
            raise serializers.ValidationError("Cliente not found.")

        if 'imovel' in attrs and not PropertiesNested.objects.get(property_id=int(attrs['imovel'])):
            raise serializers.ValidationError("Imovel is required.")
        
        return super().validate(attrs)
        
    
    def create(self, validated_data):
        
        if 'assunto' in validated_data:
            validated_data['assunto_id'] = [ObjectId(validated_data.pop('assunto'))]
        
        if 'cliente' in validated_data:
            validated_data['cliente_id'] = [ObjectId(validated_data.pop('cliente'))]

        if 'imovel' in validated_data:
            validated_data['imovel_id'] = [int(validated_data.pop('imovel'))]

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})


        obj_data['id'] = obj_data.pop('_id')
        
        if 'assunto' in obj_data:
            obj_data['assunto'] = obj_data.pop('assunto_id')
        if 'cliente' in obj_data:
            obj_data['cliente'] = obj_data.pop('cliente_id')
        if 'imovel' in obj_data:
            obj_data['imovel'] = obj_data.pop('imovel_id')
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
        
        return obj
    


    def update(self, instance, validated_data):
        
        ### Assunto ###    
        if 'assunto' in validated_data:
            validated_data['assunto_id'] = [ObjectId(validated_data.pop('assunto', []))]
        ### Cliente ###
        if 'cliente' in validated_data:
            validated_data['cliente_id'] = [ObjectId(validated_data.pop('cliente', []))]
        ### Imovel ###
        if 'imovel' in validated_data:
            validated_data['imovel_id'] = [int(validated_data.pop('imovel', []))]

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            return instance
        else:
            return None
        


class ImprensaSerializer(serializers.ModelSerializer):
    class Meta:
        model = Imprensa
        fields = '__all__'
        extra_kwargs = {
            'texto': {'required': True},
		}
    

class AssuntoOuvidoriaSerializer(serializers.ModelSerializer):
    class Meta:
        model = AssuntoOuvidoria
        fields = '__all__'
        extra_kwargs = {
            'nome': {'required': True},
			'email': {'required': True},
		}
    

class OuvidoriaReadOnlySerializer(serializers.ModelSerializer):
    
    assunto = AssuntoOuvidoriaSerializer(many=True, read_only=True)
    
    class Meta:
        model = Ouvidoria
        fields = '__all__'
        extra_kwargs = {
            'nome': {'required': True},
			'email': {'required': True},
			'telefone': {'required': True},
			'estado': {'required': True},
			'cidade': {'required': True},
			'mensagem': {'required': True},
            'assunto': {'required': True},
		}


        
class OuvidoriaWriteOnlySerializer(serializers.ModelSerializer):
    
    assunto = serializers.CharField()
    
    class Meta:
        model = Ouvidoria
        fields = '__all__'
        extra_kwargs = {
            'nome': {'required': True},
			'email': {'required': True},
			'telefone': {'required': True},
			'estado': {'required': True},
			'cidade': {'required': True},
			'mensagem': {'required': True},
		}
        
    def validate(self, attrs):
        if 'assunto' not in attrs:
            raise serializers.ValidationError("Assunto is required.")
        else:
            assunto = AssuntoOuvidoria.objects.get(id=ObjectId(attrs['assunto']))
            if not assunto:
                raise serializers.ValidationError("Assunto not found.")
            return super().validate(attrs)
    
    def create(self, validated_data):
        assunto = validated_data.pop('assunto')
        assunto_id = [ObjectId(assunto)]
        validated_data['assunto_id'] = assunto_id

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})


        obj_data['id'] = obj_data.pop('_id')
        obj_data['assunto'] = obj_data.pop('assunto_id')
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
        
        return obj

    def update(self, instance, validated_data):
            
        if 'assunto' in validated_data:
            validated_data['assunto_id'] = [ObjectId(validated_data.pop('assunto', []))]

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            return instance
        else:
            return None

class GrupoPerguntaFrequentesSerializer(serializers.ModelSerializer):
    class Meta:
        model = GrupoPerguntaFrequente
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': False},
			'nome': {'required': True},
   		}

    def create(self, validated_data):
        
        # Handle the `ordem` field logic during creation
        if 'ordem' not in validated_data or validated_data['ordem'] is None:
            # If no `ordem` is provided, gets the last ordem and increments by 1
            last_ordem = GrupoPerguntaFrequente.objects.order_by('-ordem').first()
            validated_data['ordem'] = last_ordem.ordem + 1 if last_ordem else 1

        else:
            # If `ordem` is provided, increment the `ordem` of categories with equal or greater `ordem`
            ordem = validated_data['ordem']
            categorias_to_update = GrupoPerguntaFrequente.objects.filter(ordem__gte=ordem)
            for categoria in categorias_to_update:
                categoria.ordem += 1
                categoria.save()

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj = self.Meta.model(**obj_data)
        return obj

    def update(self, instance, validated_data):

        # Handle the `ordem` field logic during update
        if 'ordem' in validated_data:
            new_ordem = validated_data.get('ordem', instance.ordem)
            if new_ordem != instance.ordem:
                if new_ordem > instance.ordem:
                    # Moving the category down in the order
                    categorias_to_update = GrupoPerguntaFrequente.objects.filter(ordem__gt=instance.ordem, ordem__lte=new_ordem)
                    for categoria in categorias_to_update:
                        categoria.ordem -= 1
                        categoria.save()
                else:
                    # Moving the category up in the order
                    categorias_to_update = GrupoPerguntaFrequente.objects.filter(ordem__lt=instance.ordem, ordem__gte=new_ordem)
                    for categoria in categorias_to_update:
                        categoria.ordem += 1
                        categoria.save()
                validated_data['ordem'] = new_ordem

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            return instance
        else:
            return None

class PerguntaFrequenteReadOnlySerializer(serializers.ModelSerializer):
    
    grupo = GrupoPerguntaFrequentesSerializer(many=True, read_only=True)
    
    class Meta:
        model = PerguntaFrequente
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': False},
			'grupo': {'required': True},
			'pergunta': {'required': True},
			'resposta': {'required': True},
		}

class PerguntaFrequenteWriteOnlySerializer(serializers.ModelSerializer):
    
    grupo = serializers.CharField()
    
    class Meta:
        model = PerguntaFrequente
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': False},
			'grupo': {'required': True},
			'pergunta': {'required': True},
			'resposta': {'required': True},
		}
        
    def validate(self, attrs):
        if 'grupo' not in attrs:
            raise serializers.ValidationError("Grupo is required.")
        else:
            grupo = GrupoPerguntaFrequente.objects.get(id=ObjectId(attrs['grupo']))
            if not grupo:
                raise serializers.ValidationError("Grupo not found.")
            return super().validate(attrs)
    
    def create(self, validated_data):
        grupo = validated_data.pop('grupo')
        grupo_id = [ObjectId(grupo)]
        validated_data['grupo_id'] = grupo_id
        
        
        # Handle the `ordem` field logic during creation
        if 'ordem' not in validated_data or validated_data['ordem'] is None:
            # If no `ordem` is provided, gets the last ordem and increments by 1
            last_ordem = PerguntaFrequente.objects.order_by('-ordem').first()
            validated_data['ordem'] = last_ordem.ordem + 1 if last_ordem else 1

        else:
            # If `ordem` is provided, increment the `ordem` of categories with equal or greater `ordem`
            ordem = validated_data['ordem']
            categorias_to_update = PerguntaFrequente.objects.filter(ordem__gte=ordem)
            for categoria in categorias_to_update:
                categoria.ordem += 1
                categoria.save()

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})


        obj_data['id'] = obj_data.pop('_id')
        obj_data['grupo'] = obj_data.pop('grupo_id')
        obj = self.Meta.model(**obj_data)
        return obj

    def update(self, instance, validated_data):
            
        if 'grupo' in validated_data:
            validated_data['grupo_id'] = [ObjectId(validated_data.pop('grupo', []))]

        # Handle the `ordem` field logic during update
        if 'ordem' in validated_data:
            new_ordem = validated_data.get('ordem', instance.ordem)
            if new_ordem != instance.ordem:
                if new_ordem > instance.ordem:
                    # Moving the category down in the order
                    categorias_to_update = PerguntaFrequente.objects.filter(ordem__gt=instance.ordem, ordem__lte=new_ordem)
                    for categoria in categorias_to_update:
                        categoria.ordem -= 1
                        categoria.save()
                else:
                    # Moving the category up in the order
                    categorias_to_update = PerguntaFrequente.objects.filter(ordem__lt=instance.ordem, ordem__gte=new_ordem)
                    for categoria in categorias_to_update:
                        categoria.ordem += 1
                        categoria.save()
                validated_data['ordem'] = new_ordem

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            return instance
        else:
            return None
            
            

class PorqueRemaxSerializer(serializers.ModelSerializer):
    class Meta:
        model = PorqueRemax
        fields = '__all__'
        extra_kwargs = {
            'texto': {'required': True},
		}
    

class RemaxNoBrasilReadOnlySerializer(serializers.ModelSerializer):
    
    agencias = AgentSerializer(many=True, read_only=True)
    corretores = OfficeSerializer(many=True, read_only=True)
    imoveis_exclusivos = PropertiesNestedSimpleSerializer(many=True, read_only=True)

    class Meta:
        model = RemaxNoBrasil
        fields = '__all__'
        extra_kwargs = {
            'texto_simplificado': {'required': True},
			'texto': {'required': True},
			'agencias': {'required': True},
			'corretores': {'required': True},
			'imoveis_exclusivos': {'required': True},
		}
    

class RemaxNoBrasilWriteOnlySerializer(serializers.ModelSerializer):
    
    agencias = serializers.CharField()
    corretores = serializers.CharField()
    imoveis_exclusivos = serializers.CharField()

    class Meta:
        model = RemaxNoBrasil
        fields = '__all__'
        extra_kwargs = {
            'texto_simplificado': {'required': True},
			'texto': {'required': True},
			'agencias': {'required': True},
			'corretores': {'required': True},
			'imoveis_exclusivos': {'required': True},
		}
    
    def validate(self, attrs):
        
        ### Agencias ###
        if 'agencias' not in attrs:
            raise serializers.ValidationError("'Agencias' is required.")
        else:
            agencias = str(attrs['agencias']).replace('[', '').replace(']', '').replace('\'', '').split(',')
            pipeline = [
                {'$match': {'office_id': {'$in': [int(agencia) for agencia in agencias]}}}
            ]
            
            #print(f"Agencias Pipeline: {pipeline}")
            
            qtd_agencias_found = len(list(Offices.objects.mongo_aggregate(pipeline)))
            
            #print(f"Agencias Found: {qtd_agencias_found}")
            
            if len(agencias) != qtd_agencias_found:
                raise serializers.ValidationError("Agencias not found.")
            
        ### Corretores ###
        if 'corretores' not in attrs:
            raise serializers.ValidationError("'Corretores' is required.")
        else:
            corretores = str(attrs['corretores']).replace('[', '').replace(']', '').replace('\'', '').split(',')
            pipeline = [
                {'$match': {'agent_id': {'$in': [int(corretor) for corretor in corretores]}}}
            ]
            
            #print(f"Corretores Pipeline: {pipeline}")
            
            qtd_corretores_found = len(list(Agents.objects.mongo_aggregate(pipeline)))
            
            #print(f"Corretores Found: {qtd_corretores_found}")
            
            if len(corretores) != qtd_corretores_found:
                raise serializers.ValidationError("Corretores not found.")
        
        ### Imoveis Exclusivos ###
        if 'imoveis_exclusivos' not in attrs:
            raise serializers.ValidationError("'Imoveis Exclusivos' is required.")
        else:
            imoveis_exclusivos = str(attrs['imoveis_exclusivos']).replace('[', '').replace(']', '').replace('\'', '').split(',')
            pipeline = [
                {'$match': {'property_id': {'$in': [int(imovel) for imovel in imoveis_exclusivos]}}}
            ]
            
            #print(f"Imoveis Exclusivos Pipeline: {pipeline}")
            
            qtd_imoveis_exclusivos_found = len(list(PropertiesNested.objects.mongo_aggregate(pipeline)))
            
            #print(f"Imoveis Exclusivos Found: {qtd_imoveis_exclusivos_found}")
            
            if len(imoveis_exclusivos) != qtd_imoveis_exclusivos_found:
                raise serializers.ValidationError("Imoveis Exclusivos not found.")
            
        return super().validate(attrs)
    
    def create(self, validated_data):
        
        ### Agencias ###
        validated_data['agencias'] = str(validated_data.pop('agencias')).replace('[', '').replace(']', '').replace('\'', '').split(',')
        validated_data['agencias_id'] = [int(agencia) for agencia in validated_data.pop('agencias')]
        ### Corretores ###
        validated_data['corretores'] = str(validated_data.pop('corretores')).replace('[', '').replace(']', '').replace('\'', '').split(',')
        validated_data['corretores_id'] = [int(corretor) for corretor in validated_data.pop('corretores')]
        ### Imoveis Exclusivos ###
        validated_data['imoveis_exclusivos'] = str(validated_data.pop('imoveis_exclusivos')).replace('[', '').replace(']', '').replace('\'', '').split(',')
        validated_data['imoveis_exclusivos_id'] = [int(imovel) for imovel in validated_data.pop('imoveis_exclusivos')]

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj_data['agencias'] = obj_data.pop('agencias_id')
        obj_data['corretores'] = obj_data.pop('corretores_id')
        obj_data['imoveis_exclusivos'] = obj_data.pop('imoveis_exclusivos_id')
  
        
        obj = self.Meta.model(**obj_data)
        
        return obj

    def update(self, instance, validated_data):
        ### Agencias ###
        if 'agencias' in validated_data:
            agencias = str(validated_data.pop('agencias')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['agencias_id'] = [int(agencia) for agencia in agencias]
        ### Corretores ###
        if 'corretores' in validated_data:
            corretores = str(validated_data.pop('corretores')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['corretores_id'] = [int(corretor) for corretor in corretores]
        ### Imoveis Exclusivos ###
        if 'imoveis_exclusivos' in validated_data:
            imoveis_exclusivos = str(validated_data.pop('imoveis_exclusivos')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['imoveis_exclusivos_id'] = [int(imovel) for imovel in imoveis_exclusivos]

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            return instance
        else:
            return None



class ReconhecimentosSerializer(serializers.ModelSerializer):
    class Meta:
        model = Reconhecimento
        fields = '__all__'
        extra_kwargs = {
			'ordem': {'required': True},
			'selo': {'required': True},
			'titulo': {'required': True},
			'status': {'required': True},
		}

class RemaxNoMundoSerializer(serializers.ModelSerializer):
    class Meta:
        model = RemaxNoMundo
        fields = '__all__'
        extra_kwargs = {
            'texto_simplificado': {'required': True},
			'texto': {'required': True},
		}


class UniversidadeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Universidade
        fields = '__all__'
        extra_kwargs = {
            'texto': {'required': True},
		}
        


class ParceiroSerializer(serializers.ModelSerializer):
    class Meta:
        model = Parceiro
        fields = '__all__'
        extra_kwargs = {
            'texto': {'required': True},
		}



class RelacaoInvestidorSerializer(serializers.ModelSerializer):
    class Meta:
        model = RelacaoInvestidor
        fields = '__all__'
        extra_kwargs = {
            'texto': {'required': True},
		}


############################################################################################################
####### EstadoDetalhe Serializer ###########################################################################
############################################################################################################

class EstadoDetalheReadOnlySerializer(serializers.ModelSerializer):
    estado_id = StateSimpleSerializer(many=True, read_only=True)
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
    class Meta:
        model = EstadoDetalhe
        fields = '__all__'
        extra_kwargs = {
            'estado_id': {'required': True},
            'texto': {'required': True},
            'imagem': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }

class EstadoDetalheWriteOnlySerializer(serializers.ModelSerializer):
    estado_id = serializers.CharField()
    
    class Meta:
        model = EstadoDetalhe
        fields = '__all__'
        extra_kwargs = {
            'estado_id': {'required': True},
            'texto': {'required': True},
            'imagem': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }

    def validate(self, attrs):
        if 'estado_id' not in attrs:
            raise serializers.ValidationError("estado_id is required.")
        else:
            estado_id = attrs['estado_id']

            try:
                estado = EstadoDetalhe.objects.get(estado_id=estado_id)
                if estado:
                    raise serializers.ValidationError("Estado Detalhe already exists.")
            except Exception as e:
                raise serializers.ValidationError(f"Error: {e}")
           
            try:
                state = State.objects.get(state_id=estado_id)
            except State.DoesNotExist:
                raise serializers.ValidationError("Invalid estado_id.")
            except Exception as e:
                raise serializers.ValidationError(f"Error: {e}")
        
        return super().validate(attrs)
    
    def create(self, validated_data):
        
        # Handle the `estado_id` field logic during creation
        validated_data['estado_id'] = [validated_data.pop('estado_id')]
        
        if 'request' in self.context:
            # Get the user ID from the request
            user_id = [ObjectId(self.context['request'].user.id)]
            validated_data['created_by'] = user_id
            # 
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')
        
        # Handle the 'created_at' field logic during creation
        validated_data['created_at'] = timezone.now()

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        
        if 'file' in locals():
            folder_name = "estados-detalhes"
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=obj_id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'imagem': file_url}})
        
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        #obj_data['estado_id'] = obj_data.pop('estado_id')
        obj = self.Meta.model(**obj_data)
        return obj

    def update(self, instance, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')

        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()
            
        if 'estado_id' in validated_data:
            validated_data['estado_id'] = [validated_data.pop('estado_id')]

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if 'file' in locals():
            folder_name = "estados-detalhes"
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=instance.id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': {'imagem': file_url}})
        

        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(instance.id)})
        
        obj_data['id'] = obj_data.pop('_id')
        obj_data['estado_id'] = obj_data.pop('estado_id')
        obj = self.Meta.model(**obj_data)
        
        return obj



############################################################################################################
####### CidadeDetalhe Serializer ###########################################################################
############################################################################################################

class CidadeDetalheReadOnlySerializer(serializers.ModelSerializer):
    cidade_id = CitySimpleSerializer(many=True, read_only=True)
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
    class Meta:
        model = CidadeDetalhe
        fields = '__all__'
        extra_kwargs = {
            'cidade_id': {'required': True},
            'texto': {'required': True},
            'imagem': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }

class CidadeDetalheWriteOnlySerializer(serializers.ModelSerializer):
    cidade_id = serializers.CharField()
    
    class Meta:
        model = CidadeDetalhe
        fields = '__all__'
        extra_kwargs = {
            'cidade_id': {'required': True},
            'texto': {'required': True},
            'imagem': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }

    def validate(self, attrs):
        if 'cidade_id' not in attrs:
            raise serializers.ValidationError("cidade_id is required.")
        else:
            cidade_id = attrs['cidade_id']

            try:
                cidade = CidadeDetalhe.objects.get(cidade_id=cidade_id)
                if cidade:
                    raise serializers.ValidationError("Cidade Detalhe already exists.")
            except Exception as e:
                raise serializers.ValidationError(f"Error: {e}")
           
            try:
                city = City.objects.get(city_id=cidade_id)
            except City.DoesNotExist:
                raise serializers.ValidationError("Invalid cidade_id.")
            except Exception as e:
                raise serializers.ValidationError(f"Error: {e}")
        
        return super().validate(attrs)
    
    def create(self, validated_data):
        
        # Handle the `cidade_id` field logic during creation
        validated_data['cidade_id'] = [validated_data.pop('cidade_id')]
        
        if 'request' in self.context:
            # Get the user ID from the request
            user_id = [ObjectId(self.context['request'].user.id)]
            validated_data['created_by'] = user_id
            # 
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')
        
        # Handle the 'created_at' field logic during creation
        validated_data['created_at'] = timezone.now()

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        
        if 'file' in locals():
            folder_name = "cidades-detalhes"
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=obj_id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'imagem': file_url}})
        
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj = self.Meta.model(**obj_data)
        return obj

    def update(self, instance, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')

        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()
            
        if 'cidade_id' in validated_data:
            validated_data['cidade_id'] = [validated_data.pop('cidade_id')]

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if 'file' in locals():
            folder_name = "cidades-detalhes"
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=instance.id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': {'imagem': file_url}})
        

        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(instance.id)})
        
        obj_data['id'] = obj_data.pop('_id')
        obj = self.Meta.model(**obj_data)
        
        return obj
    
    
    

############################################################################################################
####### BairroDetalhe Serializer ###########################################################################
############################################################################################################

class BairroDetalheReadOnlySerializer(serializers.ModelSerializer):
    bairro_id = NeighborhoodSimpleSerializer(many=True, read_only=True)
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
    class Meta:
        model = BairroDetalhe
        fields = '__all__'
        extra_kwargs = {
            'bairro_id': {'required': True},
            'texto': {'required': True},
            'imagem': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }

class BairroDetalheWriteOnlySerializer(serializers.ModelSerializer):
    bairro_id = serializers.CharField()
    
    class Meta:
        model = BairroDetalhe
        fields = '__all__'
        extra_kwargs = {
            'bairro_id': {'required': True},
            'texto': {'required': True},
            'imagem': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }

    def validate(self, attrs):
        if 'bairro_id' not in attrs:
            raise serializers.ValidationError("bairro_id is required.")
        else:
            bairro_id = attrs['bairro_id']

            try:
                bairro = BairroDetalhe.objects.get(bairro_id=bairro_id)
                if bairro:
                    raise serializers.ValidationError("Bairro Detalhe already exists.")
            except Exception as e:
                raise serializers.ValidationError(f"Error: {e}")
           
            try:
                neighborhood = Neighborhood.objects.get(neighborhood_id=bairro_id)
            except Neighborhood.DoesNotExist:
                raise serializers.ValidationError("Invalid bairro_id.")
            except Exception as e:
                raise serializers.ValidationError(f"Error: {e}")
        
        return super().validate(attrs)
    
    def create(self, validated_data):
        
        # Handle the `bairro_id` field logic during creation
        validated_data['bairro_id'] = [validated_data.pop('bairro_id')]
        
        if 'request' in self.context:
            # Get the user ID from the request
            user_id = [ObjectId(self.context['request'].user.id)]
            validated_data['created_by'] = user_id
            # 
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')
        
        # Handle the 'created_at' field logic during creation
        validated_data['created_at'] = timezone.now()

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        
        if 'file' in locals():
            folder_name = "bairros-detalhes"
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=obj_id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'imagem': file_url}})
        
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj = self.Meta.model(**obj_data)
        return obj

    def update(self, instance, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')

        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()
            
        if 'bairro_id' in validated_data:
            validated_data['bairro_id'] = [validated_data.pop('bairro_id')]

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if 'file' in locals():
            folder_name = "bairros-detalhes"
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=instance.id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': {'imagem': file_url}})
        

        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(instance.id)})
        
        obj_data['id'] = obj_data.pop('_id')
        obj = self.Meta.model(**obj_data)
        
        return obj





class ConstrutoraSerializer(serializers.ModelSerializer):
    class Meta:
        model = Construtora
        fields = '__all__'
        extra_kwargs = {
            'nome': {'required': True},
		}

class PoliticaPrivacidadeTextoSerializer(serializers.ModelSerializer):
    class Meta:
        model = PoliticaPrivacidadeTexto
        fields = '__all__'
        extra_kwargs = {
            'texto': {'required': True},
        }

class TermosDeUsoSerializer(serializers.ModelSerializer):
    class Meta:
        model = TermosDeUso
        fields = '__all__'
        extra_kwargs = {
            'content': {'required': True},
        }



class LancamentoCaracteristicasSerializer(serializers.ModelSerializer):
    class Meta:
        model = LancamentoCaracteristicas
        fields = '__all__'

##################################################

# from collections import OrderedDict
# class OrderedDictField(serializers.Field):
#     def to_representation(self, value):
#         if isinstance(value, OrderedDict):
#             return {k: str(v) if isinstance(v, ObjectId) else v for k, v in value.items()}
#         elif isinstance(value, list):
#             return [str(v) if isinstance(v, ObjectId) else v for v in value]
#         return value

#     def to_internal_value(self, data):
#         return data

# def ordered_dict_to_json(data):
#     if isinstance(data, list):
#         return [ordered_dict_to_json(item) for item in data]
#     elif isinstance(data, dict):
#         return {key: ordered_dict_to_json(value) for key, value in data.items()}
#     elif data is None:
#         return {}
#     else:
#         return data

# class LancamentoSerializer(serializers.ModelSerializer):
    
#     user_create = OrderedDictField(required=False)
#     user_update = OrderedDictField(required=False)
#     bairro = OrderedDictField()
#     cidade = OrderedDictField()
#     estado = OrderedDictField()
#     caracteristicas = OrderedDictField()

#     class Meta:
#         model = Lancamento
#         fields = '__all__'
#         extra_kwargs = {
#             'nome_do_empreendimento': {'required': True},
#             'descricao': {'required': False},
#             'endereco': {'required': False},
#             'bairro': {'required': True},
#             'cidade': {'required': True},
#             'estado': {'required': True},
#             'pais': {'required': False},
#             'latitude': {'required': False},
#             'longitude': {'required': False},
#             'estagio_de_obra': {'required': False},
#             'caracteristicas': {'required': False},
#             'user_create': {'required': False},
#             'user_update': {'required': False},
#         }
    
#     # def validate(self, attrs):
#     #     if 'bairro' not in attrs:
#     #         raise serializers.ValidationError("Bairro is required.")
#     #     return super().validate(attrs)
    
#     def create(self, validated_data):
#         # Get the user ID from the request context
#         user_id = [ObjectId(self.context['request'].user.id)]
#         #print(f"User ID: {user_id}")
        
#         # Pop the ObjectIds for related fields
#         if 'bairro' in validated_data:
#             bairro_id = [ObjectId(validated_data.pop('bairro'))]
#         #print(f"Bairro ID: {bairro_id}")
        
#         if 'cidade' in validated_data:
#             cidade_id = [ObjectId(validated_data.pop('cidade'))]
#         #print(f"Cidade ID: {cidade_id}")
        
#         if 'estado' in validated_data:
#             estado_id = [ObjectId(validated_data.pop('estado'))]
#         #print(f"Estado ID: {estado_id}")
        
#         if 'caracteristicas' in validated_data:
#             caracteristicas = validated_data.pop('caracteristicas').split(',')
#             #print(f"Caracteristicas: {caracteristicas}")
#             caracteristicas_ids = [ObjectId(caracteristica) for caracteristica in caracteristicas]
#         #print(f"Caracteristicas ID: {caracteristicas_ids}")
        
#         # Convert OrderedDict to JSON, including nested structures


#         # Fetch the full related objects using the ObjectIds
        
#         bairro_data = ordered_dict_to_json(BairroReadOnlySerializer(Bairro.objects.filter(id__in=bairro_id).first()).data)
#         #print(f"Bairro data: {bairro_data}")
#         cidade_data = ordered_dict_to_json(CidadeReadOnlySerializer(Cidade.objects.filter(id__in=cidade_id).first()).data)
#         #print(f"Cidade data: {cidade_data}")
#         estado_data = ordered_dict_to_json(EstadoSerializer(Estado.objects.filter(id__in=estado_id).first()).data)
#         #print(f"Estado data: {estado_data}")
#         caracteristicas_data = ordered_dict_to_json(FeatureSerializer(Features.objects.filter(id__in=caracteristicas_ids), many=True).data)
#         #print(f"Caracteristicas data: {caracteristicas_data}")
#         #print(f"LenCaracteristicas data: {len(caracteristicas_data)}")
#         user_create_data = [ordered_dict_to_json(UsuarioSimpleSerializer(Usuario.objects.filter(id__in=user_id).first()).data)['id']]
#         #print(f"User Create Data: {user_create_data}")
        
#         # cidade_objects = list(Cidade.objects.filter(id__in=cidade_id))
#         # print(f"Cidade Objects: {list(cidade_objects)}")
#         # estado_objects = list(Estado.objects.filter(id__in=estado_id))
#         # print(f"Estado Objects: {estado_objects}")
#         # caracteristicas_objects = list(Features.objects.filter(id__in=caracteristicas_ids))
#         # print(f"Caracteristicas Objects: {caracteristicas_objects}")
        
#         # Create the Lancamento object and attach the related objects
#         #user_create must be the user logged in
#         validated_data['user_create'] = user_create_data
#         validated_data['bairro'] = bairro_data
#         validated_data['cidade'] = cidade_data
#         validated_data['estado'] = estado_data
#         validated_data['caracteristicas'] = caracteristicas_data
#         #print(f"Validated Data: {validated_data}")
#         validated_data['created_at'] = datetime.now()
#         lancamento_id = Lancamento.objects.mongo_insert(validated_data)
#         #print(f"Lancamento ID: {lancamento_id}")
#         new_lancamento = Lancamento.objects.get(id=ObjectId(lancamento_id))
#         #lancamento = Lancamento.objects.create(**validated_data)
#         #print(f"Lancamento: {lancamento}")
#         # lancamento.bairro.set(bairro_objects)
#         # lancamento.cidade.set(cidade_objects)
#         # lancamento.estado.set(estado_objects)
#         # lancamento.caracteristicas.set(caracteristicas_objects)
        
#         return new_lancamento

#     def update(self, instance, validated_data):
#         # Get the user ID from the request context for updating user
#         user_id = [ObjectId(self.context['request'].user.id)]

#         # Pop the ObjectIds for related fields and convert them
#         if 'bairro' in validated_data:
#             bairro_id = [ObjectId(validated_data.pop('bairro'))]

#         if 'cidade' in validated_data:
#             cidade_id = [ObjectId(validated_data.pop('cidade'))]

#         if 'estado' in validated_data:
#             estado_id = [ObjectId(validated_data.pop('estado'))]

#         if 'caracteristicas' in validated_data:
#             caracteristicas = validated_data.pop('caracteristicas').split(',')
#             caracteristicas_ids = [ObjectId(caracteristica) for caracteristica in caracteristicas]

#         # Fetch the full related objects using the ObjectIds
#         bairro_data = ordered_dict_to_json(BairroReadOnlySerializer(Bairro.objects.filter(id__in=bairro_id).first()).data)
#         cidade_data = ordered_dict_to_json(CidadeReadOnlySerializer(Cidade.objects.filter(id__in=cidade_id).first()).data)
#         estado_data = ordered_dict_to_json(EstadoSerializer(Estado.objects.filter(id__in=estado_id).first()).data)
#         caracteristicas_data = ordered_dict_to_json(FeatureSerializer(Features.objects.filter(id__in=caracteristicas_ids), many=True).data)
#         user_update_data = [ordered_dict_to_json(UsuarioSimpleSerializer(Usuario.objects.filter(id__in=user_id).first()).data)['id']]

#         # Update the instance with the validated nested data
#         instance.bairro = bairro_data
#         instance.cidade = cidade_data
#         instance.estado = estado_data
#         instance.caracteristicas = caracteristicas_data
#         instance.user_update = user_update_data

#         # Update other fields with validated data
#         for attr, value in validated_data.items():
#             setattr(instance, attr, value)

#         instance.updated_at = datetime.now()
#         instance.save()
#         return instance

#################################################################

class ImageFieldForInstancePath(serializers.ImageField):
    def handle_uploaded_file(self, file, instance):
        directory = f'{instance.__class__.__name__.lower()}s/img/{instance.id}/'
        os.makedirs(directory, exist_ok=True)  # Ensure the directory exists
        file_path = default_storage.save(os.path.join(directory, file.name), ContentFile(file.read()))
        return file_path  # Return the relative path for storing in MongoDB

    def save_file(self, instance, file):
        if file:
            file_url = self.handle_uploaded_file(file, instance)
            return file_url  # Return the file URL to be saved in the instance


class DynamicJSONField(serializers.Field):
    def __init__(self, related_serializer=None, related_model=None, related_id='id', many=False, related_fields=None, insert_or_update_related_field=None, **kwargs):
        """
        :param insert_or_update_related_field: The field in the related model that should be updated after creation or update.
        """
        self.related_serializer = related_serializer
        self.related_model = related_model
        self.many = many
        self.related_fields = related_fields
        self.related_id = related_id
        self.insert_or_update_related_field = insert_or_update_related_field  # Add the insert_or_update_related_field option
        super().__init__(**kwargs)

    def clean_value(self, value):
        """
        Ensure that OrderedDict, ObjectIds, and other types are properly serialized into readable formats.
        """
        if isinstance(value, OrderedDict):
            return {k: str(v) if isinstance(v, ObjectId) else v for k, v in value.items()}
        elif isinstance(value, list):
            return [self.clean_value(v) for v in value]
        elif isinstance(value, ObjectId):
            return str(value)  # Convert ObjectId to string
        return value

    def to_representation(self, value):
        # Clean and present the value using the new clean_value method
        return self.clean_value(value)

    def to_internal_value(self, data):
        """
        Convert incoming data into the expected format.
        If many=True, data could be a comma-separated string or list.
        """
        if self.many:
            if isinstance(data, str):
                data = data.split(',')  # Split comma-separated values
            try:
                return [self.convert_to_objectid(item) for item in data]
            except Exception:
                raise serializers.ValidationError(f"Invalid ObjectId(s): {data}")
        else:
            try:
                return self.convert_to_objectid(data)
            except Exception:
                raise serializers.ValidationError(f"Invalid ObjectId: {data}")

    def convert_to_objectid(self, value):
        if isinstance(value, ObjectId):
            return value
        try:
            return ObjectId(value)
        except Exception:
            return value  # Return as is if it's not a valid ObjectId format

    def fetch_related_data(self, object_ids):
        if not isinstance(object_ids, list):
            object_ids = [object_ids]

        if self.related_fields:  # If related_fields is defined, fetch related data
            if self.related_id == 'id':
                object_ids = [self.convert_to_objectid(oid) for oid in object_ids]

            filter_kwargs = {f'{self.related_id}__in': object_ids}
            related_objects = self.related_model.objects.filter(**filter_kwargs)

            class CustomSerializer(self.related_serializer):
                class Meta(self.related_serializer.Meta):
                    fields = self.related_fields if self.related_fields else '__all__'

            serializer = CustomSerializer(related_objects, many=True)
            ## fiter serializer.data to return only the fields that are in self.related_fields
            filtered_data = []
            for item in serializer.data:
                filtered_item = {field: item[field] for field in self.related_fields if field in item}
                filtered_data.append(filtered_item)
            return filtered_data

        else:
            # No related_fields, just return ObjectId(s)
            return [self.convert_to_objectid(oid) for oid in object_ids]


class DynamicJSONModelSerializer(serializers.ModelSerializer):
    
    def to_representation(self, instance):
        """
        Ensure that the serialized data is more presentable by applying the same logic.
        """
        representation = super().to_representation(instance)
        
        # Fetch data from the model instance for fields like 'fotos'
        for field in self.Meta.model._meta.get_fields():
            field_name = field.name
            if hasattr(instance, field_name):
                # Get the actual value from the model instance
                field_value = getattr(instance, field_name)

                # Ensure lists (like 'fotos') are properly formatted
                if isinstance(field_value, list):
                    representation[field_name] = self.clean_representation(field_value)

        # Replace database field names like '_id' with model field names like 'id'
        representation = self.replace_db_field_names(representation)

        return representation

    def clean_representation(self, value):
        """
        Recursively clean lists of OrderedDicts, ObjectIds, and other types for better readability.
        """
        if isinstance(value, list):
            return [self.clean_representation(v) for v in value]
        elif isinstance(value, OrderedDict):
            return {k: str(v) if isinstance(v, ObjectId) else self.clean_representation(v) for k, v in value.items()}
        elif isinstance(value, ObjectId):
            return str(value)  # Convert ObjectId to string
        return value

    def replace_db_field_names(self, representation):
        """
        Replace database field names with the corresponding model field names (e.g., '_id' -> 'id').
        """
        field_mapping = {field.db_column or field.name: field.name for field in self.Meta.model._meta.fields}
        
        cleaned_representation = OrderedDict()
        for key, value in representation.items():
            # Map the field name from the DB field to the model field
            cleaned_key = field_mapping.get(key, key)
            cleaned_representation[cleaned_key] = value
        return cleaned_representation


    def create(self, validated_data):
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            files = self.context['request'].FILES
        else:
            user_id = validated_data.pop('created_by', None)
            files = None

        if not user_id:
            raise serializers.ValidationError("User information is missing.")

        related_fields = {}
        #print(f"Validated Data*: {validated_data}")
        validated_data_copy = validated_data.copy()
        # Process related fields
        for field_name, field_value in validated_data_copy.items():
            if isinstance(self.fields[field_name], DynamicJSONField):
                related_field = self.fields[field_name]
                #print(f"Field items: {self.fields.items()}")
                #print(f"Related Field: {related_field}")
                related_fields[field_name] = related_field.fetch_related_data(field_value)
                if related_field.insert_or_update_related_field:
                    related_field_value = field_value
                    related_field_name = field_name
            elif isinstance(self.fields[field_name], ImageFieldForInstancePath):
                validated_data.pop(field_name, None)
        #print(f"Related Fields: {related_fields}")
        #print(f"Related Fields names: {related_field.related_fields}")
        validated_data.update(related_fields)
        validated_data['created_by'] = user_id
        validated_data['created_at'] = timezone.now()

        
        
        # Insert the instance into MongoDB
        instance = self.Meta.model.objects.mongo_insert(validated_data)
        instance = self.Meta.model.objects.get(id=ObjectId(instance))

        # Handle file uploads
        if files:
            for field_name, file in files.items():
                if isinstance(self.fields[field_name], ImageFieldForInstancePath):
                    file_url = self.fields[field_name].save_file(instance, file)
                    self.Meta.model.objects.filter(id=instance.id).update(**{field_name: file_url})

        # Fetch the updated instance after file processing
        instance = self.Meta.model.objects.get(id=ObjectId(instance.id))
        # Insert or update related field in the related model if applicable
        if related_field.insert_or_update_related_field:
            self.update_related_model(related_field, instance=instance, data=validated_data, related_field_value=related_field_value, field_name=related_field_name)
        return instance

    def update(self, instance, validated_data):
        # Check if the request exists in the context
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            files = self.context['request'].FILES
        else:
            user_id = validated_data.pop('updated_by', None)
            files = None

        if not user_id:
            raise serializers.ValidationError("User information is missing.")

        related_fields = {}
        validated_data_copy = validated_data.copy()

        # Process related fields and handle insert_or_update_related_field logic
        for field_name, field_value in validated_data_copy.items():
            if isinstance(self.fields[field_name], DynamicJSONField):
                related_field = self.fields[field_name]
                related_fields[field_name] = related_field.fetch_related_data(field_value)
                if related_field.insert_or_update_related_field:
                    related_field_value = field_value
                    related_field_name = field_name
            elif isinstance(self.fields[field_name], ImageFieldForInstancePath):
                # Handle image fields separately, skipping them for now
                validated_data.pop(field_name, None)

        validated_data.update(related_fields)
        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()

        # Update the instance fields with new validated data
        for attr, value in validated_data.items():
            setattr(instance, attr, value)

        instance.save()

        # Handle file uploads after instance update
        if files:
            for field_name, file in files.items():
                if isinstance(self.fields[field_name], ImageFieldForInstancePath):
                    file_url = self.fields[field_name].save_file(instance, file)
                    self.Meta.model.objects.filter(id=instance.id).update(**{field_name: file_url})

        # Fetch the updated instance after file processing
        instance = self.Meta.model.objects.get(id=ObjectId(instance.id))

        # Insert or update related field in the related model if applicable
        if related_field.insert_or_update_related_field:
            self.update_related_model(
                related_field, instance=instance, data=validated_data, 
                related_field_value=related_field_value, field_name=related_field_name
            )

        return instance

    def update_related_model(self, related_field, instance, data, related_field_value, field_name):
        """
        Update the related model by inserting or updating the data in the specified field.
        Works generically for any field defined by insert_or_update_related_field.
        """
        #print("Here")
        related_model = related_field.related_model
        related_field_name = related_field.insert_or_update_related_field
        # print(f"Related Model: {related_model}")
        # print(f"Related field name: {related_field_name}")
        # print(f"Related field value: {related_field_value}")
        # print(f"Instance: {instance}")
        # Determine the related model instance dynamically
        related_instance_id = related_field_value
        # print(f"related_instance_id: {related_instance_id}")
        related_instance = related_model.objects.get(id=related_instance_id)
        # print(f"Related Instance: {related_instance}")
        # print(f"Instance: {instance}")

        # Get the current value of the field (e.g., `fotos`)
        current_data = related_instance.__dict__.get(related_field_name, [])
        # print(f"Current Data: {current_data}")
        
        ### checks if the related_instance_id could be changed into objectid, number or string
        if isinstance(related_instance_id, ObjectId):
            related_instance_id = ObjectId(related_instance_id)
        elif isinstance(related_instance_id, int):
            related_instance_id = int(related_instance_id)
        elif isinstance(related_instance_id, str):
            related_instance_id = str(related_instance_id)
        
        try:
            instances = list(self.Meta.model.objects.mongo_find({field_name: related_instance_id}))
            # Map instances keys with the model field names
            field_mapping = {field.db_column or field.name: field.name for field in self.Meta.model._meta.fields}
            for instance in instances:
                mapped_instance = {}
                for key, value in instance.items():
                    mapped_key = field_mapping.get(key, key)
                    mapped_instance[mapped_key] = value
                instance.clear()
                instance.update(mapped_instance)
            if not instances:
                print(f"No instances found for {field_name} with ID {related_instance_id}")
        except Exception as e:
            print(f"Error fetching instances for {field_name} with ID {related_instance_id}: {e}")
            instances = []
        print(f"Instances: {len(instances)}")
        
        ## delete the field_name from the instances
        for instance in instances:
            instance.pop(field_name, None)
            # pop null values
            instance = {k: v for k, v in instance.items() if v is not None}
        
        
        print(f"instances after delete: {instances}")
        
        
        #### updating related_instance using mongo
        related_instance = related_instance.objects.mongo_update_one({'_id': related_instance_id}, {'$set':{related_field_name: instances}})
        print(f"Related Instance after update: {related_instance}")
        
        # Ensure the related field exists on the related instance
        if not hasattr(related_instance, related_field_name):
            setattr(related_instance, related_field_name, [])

        # Update the 'fotos' field with the instances data
        setattr(related_instance, related_field_name, instances)
        related_instance.save()

# class LancamentoSerializer(DynamicJSONModelSerializer):
#     bairro = DynamicJSONField(related_serializer=BairroReadOnlySerializer, related_model=Bairro, related_fields=['id', 'nome', 'texto', 'imagem'])
#     cidade = DynamicJSONField(related_serializer=CidadeReadOnlySerializer, related_model=Cidade, related_fields=['id', 'nome', 'texto', 'imagem'])
#     estado = DynamicJSONField(related_serializer=EstadoSerializer, related_model=Estado)
#     caracteristicas = DynamicJSONField(related_serializer=FeatureSerializer, related_model=Features, related_id='feature_id', many=True)
    
#     logo = ImageFieldForInstancePath()

#     class Meta:
#         model = Lancamento
#         fields = '__all__'
#         extra_kwargs = {
#             'nome_do_empreendimento': {'required': True},
#             'logo': {'required': False},
#             'descricao': {'required': False},
#             'endereco': {'required': False},
#             'bairro': {'required': True},
#             'cidade': {'required': True},
#             'estado': {'required': True},
#             'pais': {'required': False},
#             'latitude': {'required': False},
#             'longitude': {'required': False},
#             'estagio_de_obra': {'required': False},
#             'caracteristicas': {'default': []},
#             'created_by': {'required': False},
#             'updated_by': {'required': False},
#             'fotos': {'default': []},
#             'plantas': {'default': []},
#         }


# class FotoLancamentoSerializer(DynamicJSONModelSerializer):
    
#     lancamento_id = DynamicJSONField(related_serializer=LancamentoSerializer, related_model=Lancamento, related_id='id', insert_or_update_related_field='fotos')
#     imagem = ImageFieldForInstancePath()
    
#     class Meta:
#         model = FotoLancamento
#         fields = '__all__'
#         extra_kwargs = {
#             'lancamento_id': {'required': True},
#             'imagem': {'required': True},
#             'created_by': {'required': False},
#             'updated_by': {'required': False},
#             'ordem': {'required': False}  # Allow ordem to be optional
#         }
    
#     def create(self, validated_data):
#         # Handle the `ordem` field logic during creation
#         if 'ordem' not in validated_data or validated_data['ordem'] is None:
#             # If no ordem is provided, get the last ordem and increment by 1
#             last_ordem = self.Meta.model.objects.filter(lancamento_id=[ObjectId(validated_data['lancamento_id'])]).order_by('-ordem').first()
#             if last_ordem and last_ordem.ordem:
#                 validated_data['ordem'] = last_ordem.ordem + 1
#             else:
#                 validated_data['ordem'] = 1
#         else:
#             ordem = validated_data['ordem']
#             fotos_to_update = self.Meta.model.objects.filter(lancamento_id=ObjectId(validated_data['lancamento_id']), ordem__gte=ordem)
#             for foto in fotos_to_update:
#                 foto.ordem += 1
#                 foto.save()
        
#         # Continue with the existing create logic
#         return super().create(validated_data)

#     def update(self, instance, validated_data):
#         # Handle the `ordem` field logic during update
#         new_ordem = validated_data.get('ordem', instance.ordem)
#         if new_ordem != instance.ordem:
#             if new_ordem > instance.ordem:
#                 # Moving the element down in the order
#                 fotos_to_update = self.Meta.model.objects.filter(lancamento_id=[ObjectId(instance.lancamento_id[0])], ordem__gt=instance.ordem, ordem__lte=new_ordem)
#                 for foto in fotos_to_update:
#                     foto.ordem -= 1
#                     foto.save()
#             else:
#                 # Moving the element up in the order
#                 fotos_to_update = self.Meta.model.objects.filter(lancamento_id=[ObjectId(instance.lancamento_id[0])], ordem__lt=instance.ordem, ordem__gte=new_ordem)
#                 print(fotos_to_update)
#                 for foto in fotos_to_update:
#                     foto.ordem += 1
#                     foto.save()
#             validated_data['ordem'] = new_ordem
        
#         # Continue with the existing update logic
#         return super().update(instance, validated_data)
    
    

# class PlantaLancamentoSerializer(DynamicJSONModelSerializer):
    
#     lancamento_id = DynamicJSONField(related_serializer=LancamentoSerializer, related_model=Lancamento, related_id='id', insert_or_update_related_field='plantas')
#     imagem = ImageFieldForInstancePath()
    
#     class Meta:
#         model = PlantaLancamento
#         fields = '__all__'
#         extra_kwargs = {
#             'lancamento_id': {'required': True},
#             'imagem': {'required': True},
#             'created_by': {'required': False},
#             'updated_by': {'required': False},
#             'ordem': {'required': False}  # Allow ordem to be optional
#         }
    
#     def create(self, validated_data):
#         # Handle the `ordem` field logic during creation
#         if 'ordem' not in validated_data or validated_data['ordem'] is None:
#             # If no ordem is provided, get the last ordem and increment by 1
#             last_ordem = self.Meta.model.objects.filter(lancamento_id=[ObjectId(validated_data['lancamento_id'])]).order_by('-ordem').first()
#             if last_ordem and last_ordem.ordem:
#                 validated_data['ordem'] = last_ordem.ordem + 1
#             else:
#                 validated_data['ordem'] = 1
#         else:
#             ordem = validated_data['ordem']
#             fotos_to_update = self.Meta.model.objects.filter(lancamento_id=ObjectId(validated_data['lancamento_id']), ordem__gte=ordem)
#             for foto in fotos_to_update:
#                 foto.ordem += 1
#                 foto.save()
        
#         # Continue with the existing create logic
#         return super().create(validated_data)

#     def update(self, instance, validated_data):
#         # Handle the `ordem` field logic during update
#         new_ordem = validated_data.get('ordem', instance.ordem)
#         if new_ordem != instance.ordem:
#             if new_ordem > instance.ordem:
#                 # Moving the element down in the order
#                 fotos_to_update = self.Meta.model.objects.filter(lancamento_id=[ObjectId(instance.lancamento_id[0])], ordem__gt=instance.ordem, ordem__lte=new_ordem)
#                 for foto in fotos_to_update:
#                     foto.ordem -= 1
#                     foto.save()
#             else:
#                 # Moving the element up in the order
#                 fotos_to_update = self.Meta.model.objects.filter(lancamento_id=[ObjectId(instance.lancamento_id[0])], ordem__lt=instance.ordem, ordem__gte=new_ordem)
#                 print(fotos_to_update)
#                 for foto in fotos_to_update:
#                     foto.ordem += 1
#                     foto.save()
#             validated_data['ordem'] = new_ordem
        
#         # Continue with the existing update logic
#         return super().update(instance, validated_data)



# class UnidadeLancamentoSerializer(DynamicJSONModelSerializer):
#     lancamento = DynamicJSONField(related_serializer=LancamentoSerializer, related_model=Lancamento, related_fields=['id','nome_do_empreendimento','logo','descricao','endereco','pais','latitude','longitude','estagio_de_obra','bairro','cidade','estado','caracteristicas'])
#     planta = DynamicJSONField(related_serializer=PlantaLancamentoSerializer, related_model=PlantaLancamento, related_fields=['id', 'ordem', 'imagem'])
#     #lancamento = DynamicJSONField(related_serializer=LancamentoSerializer, related_model=Lancamento, related_fields=['id','nome_do_empreendimento'])
#     #planta = DynamicJSONField(related_serializer=PlantaLancamentoSerializer, related_model=PlantaLancamento, related_fields=['id', 'imagem'])

#     class Meta:
#         model = UnidadeLancamento
#         fields = '__all__'
#         extra_kwargs = {
#             'lancamento': {'required': True},
#             'planta': {'required': True},
#             'codigo': {'required': False},
#             'descricao': {'required': False},
#             'quartos': {'required': False},
#             'vagas': {'required': False},
#             'banheiros': {'required': False},
#             'area': {'required': False},
#             'preco': {'required': False},
#             'status': {'default': 'disponivel'},
#             'fotos': {'required': False},
#             'created_by': {'required': False},
#             'updated_by': {'required': False},
#             'created_at': {'required': False},
#             'updated_at': {'required': False},
#             'fotos': {'default': []},
#         }
    

# class FotoUnidadeLancamentoSerializer(DynamicJSONModelSerializer):

#     unidade_id = DynamicJSONField(related_serializer=UnidadeLancamentoSerializer, related_model=UnidadeLancamento, related_id='id', insert_or_update_related_field='fotos')
#     imagem = ImageFieldForInstancePath()
    
#     class Meta:
#         model = FotoUnidadeLancamento
#         fields = '__all__'
#         extra_kwargs = {
#             'unidade_id': {'required': True},
#             'imagem': {'required': True},
#             'created_by': {'required': False},
#             'updated_by': {'required': False},
#             'ordem': {'required': False}  # Allow ordem to be optional
#         }
    
#     def create(self, validated_data):
#         # Handle the `ordem` field logic during creation
#         if 'ordem' not in validated_data or validated_data['ordem'] is None:
#             # If no ordem is provided, get the last ordem and increment by 1
#             last_ordem = self.Meta.model.objects.filter(unidade_id=[ObjectId(validated_data['unidade_id'])]).order_by('-ordem').first()
#             if last_ordem and last_ordem.ordem:
#                 validated_data['ordem'] = last_ordem.ordem + 1
#             else:
#                 validated_data['ordem'] = 1
#         else:
#             ordem = validated_data['ordem']
#             fotos_to_update = self.Meta.model.objects.filter(unidade_id=ObjectId(validated_data['unidade_id']), ordem__gte=ordem)
#             for foto in fotos_to_update:
#                 foto.ordem += 1
#                 foto.save()
        
#         # Continue with the existing create logic
#         return super().create(validated_data)

#     def update(self, instance, validated_data):
#         # Handle the `ordem` field logic during update
#         new_ordem = validated_data.get('ordem', instance.ordem)
#         if new_ordem != instance.ordem:
#             if new_ordem > instance.ordem:
#                 # Moving the element down in the order
#                 fotos_to_update = self.Meta.model.objects.filter(lancamento_id=[ObjectId(instance.unidade_id[0])], ordem__gt=instance.ordem, ordem__lte=new_ordem)
#                 for foto in fotos_to_update:
#                     foto.ordem -= 1
#                     foto.save()
#             else:
#                 # Moving the element up in the order
#                 fotos_to_update = self.Meta.model.objects.filter(lancamento_id=[ObjectId(instance.unidade_id[0])], ordem__lt=instance.ordem, ordem__gte=new_ordem)
#                 print(fotos_to_update)
#                 for foto in fotos_to_update:
#                     foto.ordem += 1
#                     foto.save()
#             validated_data['ordem'] = new_ordem
        
#         # Continue with the existing update logic
#         return super().update(instance, validated_data)


# class AgenciaBannerSerializer(DynamicJSONModelSerializer):
#     agencia = DynamicJSONField(related_serializer=OfficeSerializer, related_model=Offices, related_id='office_id', related_fields=['office_id','name','logo','telephone','country','state','state_abbreviation','city','address','postal_code'])
#     imagem = ImageFieldForInstancePath()
    
#     class Meta:
#         model = AgenciaBanner
#         fields = '__all__'
#         extra_kwargs = {
#             'agencia': {'required': True},
#             'imagem': {'required': True},
#             'created_by': {'required': False},
#             'updated_by': {'required': False},
#             'ordem': {'required': False}  # Allow ordem to be optional
#         }
    
#     def create(self, validated_data):
#         # Handle the `ordem` field logic during creation
#         if 'ordem' not in validated_data or validated_data['ordem'] is None:
#             # If no ordem is provided, get the last ordem and increment by 1
#             last_ordem = self.Meta.model.objects.filter(agencia=[ObjectId(validated_data['agencia'])]).order_by('-ordem').first()
#             last_ordem = last_ordem.ordem
#             if last_ordem is None:
#                 last_ordem = 0
#             validated_data['ordem'] = last_ordem + 1 if last_ordem else 1
#         else:
#             ordem = validated_data['ordem']
#             fotos_to_update = self.Meta.model.objects.filter(lancamento_id=ObjectId(validated_data['lancamento_id']), ordem__gte=ordem)
#             for foto in fotos_to_update:
#                 foto.ordem += 1
#                 foto.save()
        
#         # Continue with the existing create logic
#         return super().create(validated_data)

#     def update(self, instance, validated_data):
#         # Handle the `ordem` field logic during update
#         new_ordem = validated_data.get('ordem', instance.ordem)
#         if new_ordem != instance.ordem:
#             if new_ordem > instance.ordem:
#                 # Moving the element down in the order
#                 fotos_to_update = self.Meta.model.objects.filter(lancamento_id=[ObjectId(instance.lancamento_id[0])], ordem__gt=instance.ordem, ordem__lte=new_ordem)
#                 for foto in fotos_to_update:
#                     foto.ordem -= 1
#                     foto.save()
#             else:
#                 # Moving the element up in the order
#                 fotos_to_update = self.Meta.model.objects.filter(lancamento_id=[ObjectId(instance.lancamento_id[0])], ordem__lt=instance.ordem, ordem__gte=new_ordem)
#                 print(fotos_to_update)
#                 for foto in fotos_to_update:
#                     foto.ordem += 1
#                     foto.save()
#             validated_data['ordem'] = new_ordem
        
#         # Continue with the existing update logic
#         return super().update(instance, validated_data)
    
#################################################################



class LancamentoReadOnlySerializer(serializers.ModelSerializer):
    

    bairro_id = NeighborhoodSimpleSerializer(many=True, read_only=True)
    cidade_id = CitySimpleSerializer(many=True, read_only=True)
    estado_id = StateSimpleSerializer(many=True, read_only=True)
    #bairro_id = serializers.SerializerMethodField()
    #cidade_id = CitySimpleSerializer(many=True, read_only=True,  fields=('id', 'city_id', 'city_name','details'))
    #estado_id = StateSimpleSerializer(many=True, read_only=True, fields=('id', 'state_id', 'state_name', 'state_abbreviation', 'country_id', 'country_name', 'details'))
    caracteristicas_id = FeatureSerializer(many=True, read_only=True)
    construtora_id = ConstrutoraSerializer(many=True, read_only=True)
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    # fiels from methods
    imagens = serializers.SerializerMethodField()
    plantas = serializers.SerializerMethodField()
    #unidades = serializers.SerializerMethodField()
    # unidades_disponiveis = serializers.SerializerMethodField()
    # unidades_vendidas = serializers.SerializerMethodField()
    
    quartos = serializers.SerializerMethodField()
    vagas = serializers.SerializerMethodField()
    banheiros = serializers.SerializerMethodField()
    preco = serializers.SerializerMethodField()
    area = serializers.SerializerMethodField()
            

    def get_quartos(self, obj):
        return ', '.join(map(str, obj.quartos)) if obj.quartos else ''
    
    def get_vagas(self, obj):
        return ', '.join(map(str, obj.vagas)) if obj.vagas else ''
    
    def get_banheiros(self, obj):
        return ', '.join(map(str, obj.banheiros)) if obj.banheiros else ''
    
    def get_preco(self, obj):
        return ', '.join(map(str, obj.preco)) if obj.preco else ''
    
    def get_area(self, obj):
        return ', '.join(map(str, obj.area)) if obj.area else ''

    
    class Meta:
        model = Lancamento
        fields = '__all__'
        extra_kwargs = {
            'nome_do_empreendimento': {'required': True},
            'logo': {'required': False},
            'descricao': {'required': False},
            'endereco': {'required': False},
            'bairro_id': {'required': True},
            'cidade_id': {'required': True},
            'estado_id': {'required': True},
            'construtora_id': {'required': True},
            'pais': {'default': 'Brasil'},
            'latitude': {'required': False},
            'longitude': {'required': False},
            'estagio_de_obra': {'default': 'Lançamento'},
            'caracteristicas_id': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
            'slug': {'required': False},
            'slogan': {'required': False},
            'video': {'required': False},
            'quartos': {'required': False},
            'vagas': {'required': False},
            'banheiros': {'required': False},
            'preco': {'required': False},
            'area': {'required': False},
            }
    


    def get_imagens(self, obj):
        try:
            lancamento_id = ObjectId(obj.id)
            imagens = LancamentoImagem.objects.mongo_find({'lancamento_id': lancamento_id}).sort('ordem')
            #print(f"Imnagens Count: {imagens.count()}")

            # Check if the queryset is empty
            if not imagens.count():
                #print("No images found.")
                return []

            # Serialize the data
            serialized_data = []
            for imagem in imagens:
                imagem['id'] = str(imagem.pop('_id'))
                imagem['lancamento_id'] = str(imagem.pop('lancamento_id')[0])
                # if 'created_by' in imagem:
                #     imagem['created_by'] = str(imagem.pop('created_by')[0])
                # if 'updated_by' in imagem:
                #     imagem['updated_by'] = str(imagem.pop('updated_by'))
                if 'created_by' in imagem:
                    imagem.pop('created_by', None)
                if 'updated_by' in imagem:
                    imagem.pop('updated_by', None)
                serialized_data.append(imagem)
            #print(f"Serialized Data: {serialized_data}")
            return serialized_data

        except Exception as e:
            logger.error(f"Error: {e}")
            return []
    
    def get_plantas(self, obj):
        try:
            lancamento_id = ObjectId(obj.id)
            plantas = LancamentoPlanta.objects.mongo_find({'lancamento_id': lancamento_id}).sort('ordem')
            #print(f"Plantas Count: {plantas.count()}")

            # Check if the queryset is empty
            if not plantas.count():
                #print("No plantas found.")
                return []

            # Serialize the data
            serialized_data = []
            for planta in plantas:
                planta['id'] = str(planta.pop('_id'))
                #planta['lancamento_id'] = str(planta.pop('lancamento_id')[0])
                # if 'created_by' in planta:
                #     planta['created_by'] = str(planta.pop('created_by')[0])
                # if 'updated_by' in planta:
                #     planta['updated_by'] = str(planta.pop('updated_by'))
                if 'lancamento_id' in planta:
                    planta.pop('lancamento_id', None)
                if 'created_by' in planta:
                    planta.pop('created_by', None)
                if 'updated_by' in planta:
                    planta.pop('updated_by', None)
                
                # get_imagens
                plantas_imagens = []
                planta_id = ObjectId(planta['id'])
                imagens = LancamentoPlantaImagem.objects.mongo_find({'planta_id': planta_id}).sort('ordem')
                for imagem in imagens:
                    imagem['id'] = str(imagem.pop('_id'))
                    imagem['planta_id'] = str(imagem.pop('planta_id')[0])
                    if 'created_by' in imagem:
                        imagem.pop('created_by', None)
                    if 'updated_by' in imagem:
                        imagem.pop('updated_by', None)
                    plantas_imagens.append(imagem)
                planta.update({'imagens': plantas_imagens})
                
                serialized_data.append(planta)
            #print(f"Serialized Data: {serialized_data}")
            return serialized_data

        except Exception as e:
            logger.error(f"Error: {e}")
            return []
    
    # def get_unidades(self, obj):
    #     try:
    #         lancamento_id = ObjectId(obj.id)
    #         unidades = LancamentoUnidade.objects.mongo_find({'lancamento_id': lancamento_id}).sort('ordem')
    #         #print(f"Unidades Count: {unidades.count()}")

    #         # Check if the queryset is empty
    #         if not unidades.count():
    #             #print("No unidades found.")
    #             return []

    #         # Serialize the data
    #         serialized_data = []
    #         for unidade in unidades:
    #             unidade['id'] = str(unidade.pop('_id'))
    #             #unidade['lancamento_id'] = str(unidade.pop('lancamento_id')[0])
    #             unidade['planta_id'] = str(unidade.pop('planta_id')[0])
    #             # if 'created_by' in unidade:
    #             #     unidade['created_by'] = str(unidade.pop('created_by')[0])
    #             # if 'updated_by' in unidade:
    #             #     unidade['updated_by'] = str(unidade.pop('updated_by'))
    #             if 'lancamento_id' in unidade:
    #                 unidade.pop('lancamento_id', None)
    #             if 'created_by' in unidade:
    #                 unidade.pop('created_by', None)
    #             if 'updated_by' in unidade:
    #                 unidade.pop('updated_by', None)
    #             serialized_data.append(unidade)
    #         #print(f"Serialized Data: {serialized_data}")
    #         return serialized_data

        except Exception as e:
            logger.error(f"Error: {e}")
            return []
    
    # def get_plantas(self, obj):
    #     return LancamentoPlantaReadOnlySerializer(LancamentoPlanta.objects.filter(lancamento_id=obj.id), many=True).data
    
    # def get_unidades(self, obj):
    #     return LancamentoUnidadeReadOnlySerializer(LancamentoUnidade.objects.filter(lancamento_id=obj.id), many=True).data
    
    # def get_unidades_disponiveis(self, obj):
    #     return LancamentoUnidadeReadOnlySerializer(LancamentoUnidade.objects.filter(lancamento_id=obj.id, status='disponivel'), many=True).data
    
    # def get_unidades_vendidas(self, obj):
    #     return LancamentoUnidadeReadOnlySerializer(LancamentoUnidade.objects.filter(lancamento_id=obj.id, status='vendido'), many=True).data

class LancamentoWriteOnlySerializer(serializers.ModelSerializer):
    
    bairro_id = serializers.CharField()
    cidade_id = serializers.CharField()
    estado_id = serializers.CharField()
    caracteristicas_id = serializers.CharField()
    construtora_id = serializers.CharField()
    
    class Meta:
        model = Lancamento
        fields = '__all__'
        extra_kwargs = {
            'nome_do_empreendimento': {'required': True},
            'logo': {'required': False},
            'descricao': {'required': True},
            'endereco': {'required': True},
            'bairro_id': {'required': True},
            'cidade_id': {'required': True},
            'estado_id': {'required': True},
            'construtora_id': {'required': True},
            'pais': {'default': 'Brasil'},
            'latitude': {'required': False},
            'longitude': {'required': False},
            'estagio_de_obra': {'default': 'Lançamento'},
            'caracteristicas_id': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
            'slug': {'required': False},
            'slogan': {'required': False},
            'video': {'required': False},
            'quartos': {'required': False},
            'vagas': {'required': False},
            'banheiros': {'required': False},
            'preco': {'required': False},
            'area': {'required': False},
            }
    
    def validate(self, attrs):
        if 'bairro_id' in attrs:
            bairro_id = Neighborhood.objects.get(neighborhood_id=int(attrs['bairro_id']))
            if not bairro_id:
                raise serializers.ValidationError("Bairro not found.")
        
        if 'cidade_id' in attrs:
            cidade_id = City.objects.get(city_id=int(attrs['cidade_id']))
            if not cidade_id:
                raise serializers.ValidationError("Cidade not found.")
        
        if 'estado_id' in attrs:
            estado_id = State.objects.get(state_id=int(attrs['estado_id']))
            if not estado_id:
                raise serializers.ValidationError("Estado not found.")
            
        if 'construtora_id' in attrs:
            construtora_id = Construtora.objects.get(id=ObjectId(attrs['construtora_id']))
            if not construtora_id:
                raise serializers.ValidationError("Construtora not found.")
        
        if 'caracteristicas_id' in attrs:
            caracteristicas = str(attrs['caracteristicas_id']).replace('[', '').replace(']', '').replace('\'', '').split(',')
            qtd_caracteristicas_found = len(list(Features.objects.filter(feature_id__in=[int(caracteristica) for caracteristica in caracteristicas])))
            if len(caracteristicas) != qtd_caracteristicas_found:
                raise serializers.ValidationError("Caracteristicas not found.")
        return super().validate(attrs)
    
    def create(self, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'logo' in self.context['request'].FILES:
                file = self.context['request'].FILES['logo']
                validated_data.pop('logo')
            
        validated_data['created_by'] = user_id
        validated_data['created_at'] = timezone.now()
        
        
        ### Bairro ###
        if 'bairro_id' in validated_data:
            validated_data['bairro_id'] = [int(validated_data.pop('bairro_id'))]

        ### Cidade ###
        if 'cidade_id' in validated_data:
            validated_data['cidade_id'] = [int(validated_data.pop('cidade_id'))]

        ### Estado ###
        if 'estado_id' in validated_data:
            validated_data['estado_id'] = [int(validated_data.pop('estado_id'))]

        ### Construtora ###
        if 'construtora_id' in validated_data:
            validated_data['construtora_id'] = [ObjectId(validated_data.pop('construtora_id'))]
            
        ### Caracteristicas ###
        if 'caracteristicas_id' in validated_data:
            caracteristicas = str(validated_data.pop('caracteristicas_id')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['caracteristicas_id'] = [int(caracteristica) for caracteristica in caracteristicas]

        # Insert the data into MongoDB
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
        # Prepare data for the Post instance
        obj_data['id'] = obj_data.pop('_id')
        
        if 'file' in locals():
            folder_name = 'lancamentos'
            file_url = handle_uploaded_file(file, folder_name=folder_name, instance_id=obj_id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'logo': file_url}})
        
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
 
        return obj

    
    def update(self, instance, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'logo' in self.context['request'].FILES:
                file = self.context['request'].FILES['logo']
                validated_data.pop('logo')

        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()
        
        ### Bairro ###
        if 'bairro_id' in validated_data:
            validated_data['bairro_id'] = [int(validated_data.pop('bairro_id'))]

        ### Cidade ###
        if 'cidade_id' in validated_data:
            validated_data['cidade_id'] = [int(validated_data.pop('cidade_id'))]

        ### Estado ###
        if 'estado_id' in validated_data:
            validated_data['estado_id'] = [int(validated_data.pop('estado_id'))]

        ### Construtora ###
        if 'construtora_id' in validated_data:
            validated_data['construtora_id'] = [ObjectId(validated_data.pop('construtora_id'))]
            
        ### Caracteristicas ###
        if 'caracteristicas_id' in validated_data:
            caracteristicas = str(validated_data.pop('caracteristicas_id')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['caracteristicas_id'] = [int(caracteristica) for caracteristica in caracteristicas]

        if 'file' in locals():
            folder_name = "lancamentos"
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=instance.id)
            if file_url:
                validated_data['logo'] = file_url

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})

        if obj:
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=False)
            return instance
        else:
            return None
    

class LancamentoImagemUploadMultipleSerializer(serializers.ModelSerializer):
    class Meta:
        model = LancamentoImagem
        fields = ['imagem', 'lancamento_id']
        extra_kwargs = {
            'lancamento_id': {'required': True},
            'imagem': {'required': True},
        }   
    

class LancamentoImagemReadOnlySerializer(serializers.ModelSerializer):
    
    lancamento_id = LancamentoReadOnlySerializer(many=True, read_only=True)
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
    class Meta:
        model = LancamentoImagem
        fields = '__all__'
        extra_kwargs = {
                'ordem': {'required': False},
                'imagem': {'required': True},
                'titulo': {'required': False},
                'principal': {'default': False},
                'lancamento_id': {'required': True},
                'created_by': {'required': False},
                'updated_by': {'required': False},
            }


class LancamentoImagemWriteOnlySerializer(serializers.ModelSerializer):
    
    lancamento_id = serializers.CharField()
    
    class Meta:
        model = LancamentoImagem
        fields = '__all__'
        extra_kwargs = {
                'ordem': {'required': False},
                'imagem': {'required': True},
                'titulo': {'required': False},
                'principal': {'default': False},
                'lancamento_id': {'required': True},
                'created_by': {'required': False},
                'updated_by': {'required': False},
            }
    
    def validate(self, attrs):
        # verify if the imagem is in image format and if it is jpg, jpeg, png or gif
        if 'imagem' in attrs:
            file = attrs['imagem']
            if not file.name.lower().endswith(('.jpg', '.jpeg', '.png', '.gif','webp')):
                raise serializers.ValidationError("Invalid image format. Only JPG, JPEG, PNG, WEBP and GIF are allowed.")
            else:
                if file.content_type not in ['image/jpeg', 'image/png', 'image/gif', 'image/webp']:
                    raise serializers.ValidationError("Invalid image content type. Only JPG, JPEG, PNG, WEBP and GIF are allowed. Extension do not match to its content.")
        
        return super().validate(attrs)
    
    def create(self, validated_data):
        #print(f"Validated Data: {validated_data}")
        #logger.info(f"Validated Data: {validated_data}")
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            # if 'imagem' in self.context['request'].FILES:
            #     file = self.context['request'].FILES['imagem']
            #     print(f"File: {file}")
            #     validated_data.pop('imagem')
        
        file = validated_data.pop('imagem')
        

        validated_data['created_by'] = user_id
        #print(f"Created By: {validated_data['created_by']}")
        validated_data['created_at'] = timezone.now()
        #print(f"Created At: {validated_data['created_at']}")
               
            
        # Handle the `ordem` field logic during creation
        if 'ordem' not in validated_data or validated_data['ordem'] is None:
            # If no `ordem` is provided, gets the last ordem and increments by 1
            last_ordem = self.Meta.model.objects.filter(lancamento_id=[ObjectId(validated_data['lancamento_id'])]).order_by('-ordem').first()
            validated_data['ordem'] = last_ordem.ordem + 1 if last_ordem else 1
        else:
            ordem = validated_data['ordem']
            fotos_to_update = self.Meta.model.objects.filter(ordem__gte=ordem, lancamento_id=[ObjectId(validated_data['lancamento_id'])])
            for foto in fotos_to_update:
                foto.ordem += 1
                foto.save()
        
         ### Lancamento ###
        validated_data['lancamento_id'] = [ObjectId(validated_data.pop('lancamento_id'))]
        #print(f"Lancamento ID: {validated_data['lancamento_id']}")
        
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        

        
        if 'file' in locals():
            
            folder_name = "lancamentos_imagens"
            
            foreign_id = validated_data['lancamento_id'][0]
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=obj_id, multiple=True, foreign_id=foreign_id)  
            #logger.info(f"File URL: {file_url}")

            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'imagem': file_url}})
        
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
        obj_data['id'] = obj_data.pop('_id')
        
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
        return obj

    def update(self, instance, validated_data):
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')

        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()
        
        if 'ordem' in validated_data:
            # Handle the `ordem` field logic during update
            new_ordem = validated_data.get('ordem', instance.ordem)
            if new_ordem != instance.ordem:
                lancamento = self.Meta.model.objects.mongo_find_one({'_id': instance.id}, {'lancamento_id': 1, '_id': 0})
                instance_lancamento_id = lancamento['lancamento_id'][0] if 'lancamento_id' in lancamento else None
                if new_ordem > instance.ordem:
                    # Moving the category down in the order
                    fotos_to_update = self.Meta.model.objects.filter(ordem__gt=instance.ordem, ordem__lte=new_ordem, lancamento_id=[ObjectId(instance_lancamento_id)])
                    for foto in fotos_to_update:
                        foto.ordem -= 1
                        foto.save()
                else:
                    # Moving the category up in the order
                    fotos_to_update = self.Meta.model.objects.filter(ordem__lt=instance.ordem, ordem__gte=new_ordem, lancamento_id=[ObjectId(instance_lancamento_id)])
                    for foto in fotos_to_update:
                        foto.ordem += 1
                        foto.save()
                validated_data['ordem'] = new_ordem
        
         ### Lancamento ###
        if 'lancamento_id' in validated_data:
            validated_data['lancamento_id'] = [ObjectId(validated_data.pop('lancamento_id', []))]
          
        if 'file' in locals():
            folder_name = "lancamentos_imagens"
            foreign_id = validated_data['lancamento_id'][0] if 'lancamento_id' in validated_data else instance.lancamento_id[0]
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, multiple=True, foreign_id=foreign_id, instance_id=instance.id)
            if file_url:
                validated_data['imagem'] = file_url

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})

        if obj:
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=instance, created=False)
            return instance
        else:
            return None



# class LancamentoPlantaReadOnlySerializer(serializers.ModelSerializer):
    
#     lancamento_id = LancamentoReadOnlySerializer(many=True, read_only=True)
#     created_by = UsuarioSimpleSerializer(many=True, read_only=True)
#     updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
#     class Meta:
#         model = LancamentoPlanta
#         fields = '__all__'
#         extra_kwargs = {
#             'ordem': {'required': False},
#             'imagem': {'required': True},
#             'titulo': {'required': False},
#             'lancamento_id': {'required': True},
#             'created_by': {'required': False},
#             'updated_by': {'required': False},
#         }


# class LancamentoPlantaWriteOnlySerializer(serializers.ModelSerializer):
    
#     lancamento_id = serializers.CharField()
    
#     class Meta:
#         model = LancamentoPlanta
#         fields = '__all__'
#         extra_kwargs = {
#             'ordem': {'required': False},
#             'imagem': {'required': True},
#             'titulo': {'required': False},
#             'lancamento_id': {'required': True},
#             'created_by': {'required': False},
#             'updated_by': {'required': False},
#         }
    
#     def create(self, validated_data):
#         if 'request' in self.context:
#             user_id = [ObjectId(self.context['request'].user.id)]
#             if 'imagem' in self.context['request'].FILES:
#                 file = self.context['request'].FILES['imagem']
#                 validated_data.pop('imagem')

#         validated_data['created_by'] = user_id
#         validated_data['created_at'] = timezone.now()
        
#         # Handle the `ordem` field logic during creation
#         if 'ordem' not in validated_data or validated_data['ordem'] is None:
#             # If no `ordem` is provided, gets the last ordem and increments by 1
#             last_ordem = self.Meta.model.objects.filter(lancamento_id=ObjectId(validated_data['lancamento_id'])).order_by('-ordem').first()
#             validated_data['ordem'] = last_ordem.ordem + 1 if last_ordem else 1
#         else:
#             ordem = validated_data['ordem']
#             fotos_to_update = self.Meta.model.objects.filter(ordem__gte=ordem, lancamento_id=ObjectId(validated_data['lancamento_id']))
#             for foto in fotos_to_update:
#                 foto.ordem += 1
#                 foto.save()
        
#          ### Lancamento ###
#         validated_data['lancamento_id'] = [ObjectId(validated_data.pop('lancamento_id'))]
        
#         obj_id = self.Meta.model.objects.mongo_insert(validated_data)
#         obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
#         obj_data['id'] = obj_data.pop('_id')
        
#         if 'file' in locals():
#             folder_name = "lancamentos_plantas"
#             file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=obj_id)
#             if file_url:
#                 file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'imagem': file_url}})
        
#         obj = self.Meta.model(**obj_data)
        
#         if obj:
#             ## call post_save signal
#             from django.db.models.signals import post_save
#             post_save.send(sender=self.Meta.model, instance=obj, created=True)
 
#         return obj

#     def update(self, instance, validated_data):
#         if 'request' in self.context:
#             user_id = [ObjectId(self.context['request'].user.id)]
#             if 'imagem' in self.context['request'].FILES:
#                 file = self.context['request'].FILES['imagem']
#                 validated_data.pop('imagem')

#         validated_data['updated_by'] = user_id
#         validated_data['updated_at'] = timezone.now()
        
#         if 'ordem' in validated_data:
#             # Handle the `ordem` field logic during update
#             new_ordem = validated_data.get('ordem', instance.ordem)
#             if new_ordem != instance.ordem:
#                 lancamento = self.Meta.model.objects.mongo_find_one({'_id': instance.id}, {'lancamento_id': 1, '_id': 0})
#                 instance_lancamento_id = lancamento['lancamento_id'][0] if 'lancamento_id' in lancamento else None
#                 if new_ordem > instance.ordem:
#                     # Moving the category down in the order
#                     fotos_to_update = self.Meta.model.objects.filter(ordem__gt=instance.ordem, ordem__lte=new_ordem, lancamento_id=[ObjectId(instance_lancamento_id)])
#                     for foto in fotos_to_update:
#                         foto.ordem -= 1
#                         foto.save()
#                 else:
#                     # Moving the category up in the order
#                     fotos_to_update = self.Meta.model.objects.filter(ordem__lt=instance.ordem, ordem__gte=new_ordem, lancamento_id=[ObjectId(instance_lancamento_id)])
#                     for foto in fotos_to_update:
#                         foto.ordem += 1
#                         foto.save()
#                 validated_data['ordem'] = new_ordem
        
#          ### Lancamento ###
#         if 'lancamento_id' in validated_data:
#             validated_data['lancamento_id'] = [ObjectId(validated_data.pop('lancamento_id', []))]
        
#         if 'file' in locals():
#             folder_name = "lancamentos_plantas"    
#             file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=instance.id)
#             if file_url:
#                 validated_data['imagem'] = file_url

#         obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})

#         if obj:
#             from django.db.models.signals import post_save
#             post_save.send(sender=self.Meta.model, instance=instance, created=False)
#             return instance
#         else:
#             return None


class LancamentoPlantaReadOnlySerializer(serializers.ModelSerializer):
    
    #planta_id = LancamentoPlantaReadOnlySerializer(many=True, read_only=True)
    lancamento_id = LancamentoReadOnlySerializer(many=True, read_only=True)
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
    class Meta:
        model = LancamentoPlanta
        fields = '__all__'
        extra_kwargs = {
                'codigo': {'required': False},
                'descricao': {'required': False},
                'quartos': {'required': False},
                'vagas': {'required': False},
                'banheiros': {'required': False},
                'area': {'required': False},
                'preco': {'required': False},
                'status': {'required': False},
                'planta_id': {'required': True},
                'lancamento_id': {'required': True},
                'created_by': {'required': False},
                'updated_by': {'required': False},
                'slug': {'required': False},
            }



class LancamentoPlantaWriteOnlySerializer(serializers.ModelSerializer):
        
    #planta_id = serializers.CharField()
    lancamento_id = serializers.CharField()
        
    class Meta:
        model = LancamentoPlanta
        fields = '__all__'
        extra_kwargs = {
                'codigo': {'required': False},
                'descricao': {'required': False},
                'quartos': {'required': False},
                'vagas': {'required': False},
                'banheiros': {'required': False},
                'area': {'required': False},
                'preco': {'required': False},
                'status': {'required': False},
                'lancamento_id': {'required': True},
                'created_by': {'required': False},
                'updated_by': {'required': False},
                'slug': {'required': False},
            }
        
    def validate(self, attrs):
        # if 'planta_id' in attrs:
        #     planta = LancamentoPlanta.objects.get(id=ObjectId(attrs['planta_id']))
        #     if not planta:
        #         raise serializers.ValidationError("Planta not found.")
            
        if 'lancamento_id'in attrs:
            lancamento = Lancamento.objects.get(id=ObjectId(attrs['lancamento_id']))
            if not lancamento:
                raise serializers.ValidationError("Lancamento not found.")
        
        # if 'lancamento_id' in attrs and 'planta_id' in attrs:
        #     lancamento_planta = LancamentoPlanta.objects.filter(lancamento_id=ObjectId(attrs['lancamento_id']), id=ObjectId(attrs['planta_id']))
        #     if not lancamento_planta:
        #         raise serializers.ValidationError("Lancamento and Planta not related.")
            
        return super().validate(attrs)
        
    def create(self, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]

        validated_data['created_by'] = user_id
        validated_data['created_at'] = timezone.now()
                
        # ### Planta ###
        # validated_data['planta_id'] = [ObjectId(validated_data.pop('planta_id'))]
        ### Lancamento ###
        validated_data['lancamento_id'] = [ObjectId(validated_data.pop('lancamento_id'))]
        ### Area ###
        if 'area' in validated_data:
            validated_data['area'] = float(validated_data['area'])
        ### Preco ###
        if 'preco' in validated_data:
            validated_data['preco'] = float(validated_data['preco'])
        
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
        obj_data['id'] = obj_data.pop('_id')
        
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
 
        return obj

        
    def update(self, instance, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]

        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()
                
        # ### Planta ###
        # if 'planta_id' in validated_data:
        #     validated_data['planta_id'] = [ObjectId(validated_data.pop('planta_id', []))]
        ### Lancamento ###
        if 'lancamento_id' in validated_data:
            validated_data['lancamento_id'] = [ObjectId(validated_data.pop('lancamento_id', []))]
        ### Area ###
        if 'area' in validated_data:
            validated_data['area'] = float(validated_data['area'])
        ### Preco ###
        if 'preco' in validated_data:
            validated_data['preco'] = float(validated_data['preco'])
        
        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        #print(obj)
        if obj:
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=instance, created=False)
            return instance
        else:
            return None
        

class LancamentoPlantaImagemUploadMultipleSerializer(serializers.ModelSerializer):
    class Meta:
        model = LancamentoPlantaImagem
        fields = ['imagem', 'planta_id']
        extra_kwargs = {
            'planta_id': {'required': True},
            'imagem': {'required': True},
        }  

class LancamentoPlantaImagemReadOnlySerializer(serializers.ModelSerializer):
    
    planta_id = LancamentoPlantaReadOnlySerializer(many=True, read_only=True)
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
    class Meta:
        model = LancamentoPlantaImagem
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': False},
            'imagem': {'required': True},
            'titulo': {'required': False},
            'principal': {'default': False},
            'planta_id': {'required': True},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }        

class LancamentoPlantaImagemWriteOnlySerializer(serializers.ModelSerializer):
    
    planta_id = serializers.CharField()
    
    class Meta:
        model = LancamentoPlantaImagem
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': False},
            'imagem': {'required': True},
            'titulo': {'required': False},
            'principal': {'default': False},
            'planta_id': {'required': True},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }
    
    def validate(self, attrs):
        # if 'planta_id' in attrs:
        #     planta = LancamentoPlanta.objects.get(id=ObjectId(attrs['planta_id']))
        #     if not planta:
        #         raise serializers.ValidationError("Planta not found.")
            
        if 'planta_id'in attrs:
            planta = LancamentoPlanta.objects.get(id=ObjectId(attrs['planta_id']))
            if not planta:
                raise serializers.ValidationError("Planta not found.")
        else:
            raise serializers.ValidationError("planta_id is missing")
            
        return super().validate(attrs)
    
    def create(self, validated_data):
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            # if 'imagem' in self.context['request'].FILES:
            #     file = self.context['request'].FILES['imagem']
            #     validated_data.pop('imagem')

        file = validated_data.pop('imagem')

        validated_data['created_by'] = user_id
        validated_data['created_at'] = timezone.now()
        
        # Handle the `ordem` field logic during creation
        if 'ordem' not in validated_data or validated_data['ordem'] is None:
            # If no `ordem` is provided, gets the last ordem and increments by 1
            last_ordem = self.Meta.model.objects.filter(planta_id=[ObjectId(validated_data['planta_id'])]).order_by('-ordem').first()
            validated_data['ordem'] = last_ordem.ordem + 1 if last_ordem else 1
        else:
            ordem = validated_data['ordem']
            fotos_to_update = self.Meta.model.objects.filter(ordem__gte=ordem, planta_id=[ObjectId(validated_data['planta_id'])])
            for foto in fotos_to_update:
                foto.ordem += 1
                foto.save()
        
         ### Lancamento ###
        validated_data['planta_id'] = [ObjectId(validated_data.pop('planta_id'))]
        
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        
        if 'file' in locals():
            folder_name = "lancamentos_plantas_imagens"
            foreign_id = validated_data['planta_id'][0]
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=obj_id, multiple=True, foreign_id=foreign_id)  
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'imagem': file_url}})
                
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
        obj_data['id'] = obj_data.pop('_id')
        
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
 
        return obj

    def update(self, instance, validated_data):
                
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')

        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()
        
        if 'ordem' in validated_data:
            # Handle the `ordem` field logic during update
            new_ordem = validated_data.get('ordem', instance.ordem)
            if new_ordem != instance.ordem:
                planta = self.Meta.model.objects.mongo_find_one({'_id': instance.id}, {'planta_id': 1, '_id': 0})
                instance_planta_id = planta['planta_id'][0] if 'planta_id' in planta else None
                if new_ordem > instance.ordem:
                    # Moving the category down in the order
                    fotos_to_update = self.Meta.model.objects.filter(ordem__gt=instance.ordem, ordem__lte=new_ordem, planta_id=[ObjectId(instance_planta_id)])
                    for foto in fotos_to_update:
                        foto.ordem -= 1
                        foto.save()
                else:
                    # Moving the category up in the order
                    fotos_to_update = self.Meta.model.objects.filter(ordem__lt=instance.ordem, ordem__gte=new_ordem, planta_id=[ObjectId(instance_planta_id)])
                    for foto in fotos_to_update:
                        foto.ordem += 1
                        foto.save()
                validated_data['ordem'] = new_ordem
        
         ### Lancamento ###
        if 'planta_id' in validated_data:
            validated_data['planta_id'] = [ObjectId(validated_data.pop('planta_id', []))]
        
        if 'file' in locals():
            folder_name = "lancamentos_plantas_imagens"
            foreign_id = validated_data['planta_id'][0] if 'planta_id' in validated_data else instance.planta_id[0]
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, multiple=True, foreign_id=foreign_id, instance_id=instance.id)
            if file_url:
                validated_data['imagem'] = file_url
        
        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=instance, created=False)
            return instance
        else:
            return None

class AgenciasBannerReadOnlySerializer(serializers.ModelSerializer):
        
        agencia_id = OfficeSerializer(many=True, read_only=True)
        created_by = UsuarioSimpleSerializer(many=True, read_only=True)
        updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
        
        class Meta:
            model = AgenciaBanner
            fields = '__all__'
            extra_kwargs = {
            'ordem': {'required': False},
            'descricao': {'required': False},
            'imagem': {'required': True},
            'link': {'required': True},
            'nova_janela': {'default': False},
            'status': {'default': 'Ativo'},
            'agencia_id': {'required': True},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }


class AgenciasBannerWriteOnlySerializer(serializers.ModelSerializer):
    
    agencia_id = serializers.CharField()
    
    class Meta:
        model = AgenciaBanner
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': False},
            'descricao': {'required': False},
            'imagem': {'required': True},
            'link': {'required': True},
            'nova_janela': {'required': False},
            'status': {'required': True},
            'agencia_id': {'required': True},
            'created_by': {'required': False},
            'updated_by': {'required': False},
        }
    
    def validate(self, attrs):
        if 'agencia_id' in attrs:
            agencia = Offices.objects.get(office_id=int(attrs['agencia_id']))
            if not agencia:
                raise serializers.ValidationError("Agencia not found.")
        return super().validate(attrs)
    
    def create(self, validated_data):
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')

        validated_data['created_by'] = user_id
        validated_data['created_at'] = timezone.now()
        
        # Handle the `ordem` field logic during creation
        if 'ordem' not in validated_data or validated_data['ordem'] is None:
            # If no `ordem` is provided, gets the last ordem and increments by 1
            # last_ordem = list(self.Meta.model.objects.mongo_aggregate([
            #     {'$match': {'agencia_id': [int(validated_data['agencia_id'])]}},
            #     {'$sort': {'ordem': -1}},
            #     {'$limit': 1}
            # ]))
            # last_ordem = last_ordem[0]['ordem'] if last_ordem else None
            # validated_data['ordem'] = last_ordem + 1 if last_ordem else 1
            last_ordem = self.Meta.model.objects.filter(agencia_id=int(validated_data['agencia_id'])).order_by('-ordem').first()
            validated_data['ordem'] = last_ordem.ordem + 1 if last_ordem else 1
        else:
            ordem = validated_data['ordem']
            fotos_to_update = self.Meta.model.objects.filter(ordem__gte=ordem, agencia_id=int(validated_data['agencia_id']))
            for foto in fotos_to_update:
                foto.ordem += 1
                foto.save()
        
        ### Lancamento ###
        validated_data['agencia_id'] = [int(validated_data.pop('agencia_id'))]
        
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
        obj_data['id'] = obj_data.pop('_id')
        
        if 'file' in locals():
            folder_name = "agencias_banners"
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=obj_id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'imagem': file_url}})
        
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
 
        return obj

    def update(self, instance, validated_data):
                
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'imagem' in self.context['request'].FILES:
                file = self.context['request'].FILES['imagem']
                validated_data.pop('imagem')

        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()
        
        if 'ordem' in validated_data:
            # Handle the `ordem` field logic during update
            new_ordem = validated_data.get('ordem', instance.ordem)
            if new_ordem != instance.ordem:
                agencia = self.Meta.model.objects.mongo_find_one({'_id': instance.id}, {'agencia_id': 1, '_id': 0})
                instance_agencia_id = agencia['agencia_id'][0] if 'agencia_id' in agencia else None
                if new_ordem > instance.ordem:
                    # Moving the category down in the order
                    fotos_to_update = self.Meta.model.objects.filter(ordem__gt=instance.ordem, ordem__lte=new_ordem, agencia_id__in=instance_agencia_id)
                    for foto in fotos_to_update:
                        foto.ordem -= 1
                        foto.save()
                else:
                    # Moving the category up in the order
                    fotos_to_update = self.Meta.model.objects.filter(ordem__lt=instance.ordem, ordem__gte=new_ordem, agencia_id__in=instance_agencia_id)
                    for foto in fotos_to_update:
                        foto.ordem += 1
                        foto.save()
                validated_data['ordem'] = new_ordem
        
         ### Lancamento ###
        if 'agencia_id' in validated_data:
            validated_data['agencia_id'] = [int(validated_data.pop('agencia_id', []))]
        
        if 'file' in locals():
            folder_name = "agencias_banners"
            file_url = handle_uploaded_file(file=file, folder_name=folder_name, instance_id=instance.id)
            if file_url:
                validated_data['imagem'] = file_url
        
        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        if obj:
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=instance, created=False)
            return instance
        else:
            return None
        
        


### ContatoDireto Serializer ###
class ContatoDiretoReadOnlySerializer(serializers.ModelSerializer):
    
    agent_id = AgentSerializer(many=True, read_only=True)
    office_id = OfficeSerializer(many=True, read_only=True)
    cliente_id = ClienteSerializer(many=True, read_only=True)
    cidade_id = CitySimpleSerializer(many=True, read_only=True)
    estado_id = StateSimpleSerializer(many=True, read_only=True)
    imovel_id = PropertiesNestedSimpleSerializer(many=True, read_only=True)
    
    class Meta:
        model = ContatoDireto
        fields = '__all__'
        extra_kwargs = {
                'nome': {'required': True},
                'email': {'required': True},
                'telefone': {'required': True},
                'mensagem': {'required': True},
                'tipo': {'required': False},
                'whatsapp': {'default': False},
                'news': {'default': False},
                'rastreamento': {'default': []},
                'agent_id': {'required': False},
                'office_id': {'required': False},
                'cliente_id': {'required': False},
                'cidade_id': {'required': False},
                'estado_id': {'required': False},
                'imovel_id': {'required': False},
            }



class ContatoDiretoWriteOnlySerializer(serializers.ModelSerializer):
        
    agent_id = serializers.CharField()
    office_id = serializers.CharField()
    cliente_id = serializers.CharField()
    cidade_id = serializers.CharField()
    estado_id = serializers.CharField()
    imovel_id = serializers.CharField()
        
    class Meta:
        model = ContatoDireto
        fields = '__all__'
        extra_kwargs = {
                'nome': {'required': True},
                'email': {'required': True},
                'telefone': {'required': True},
                'mensagem': {'required': True},
                'whatsapp': {'default': False},
                'news': {'default': False},
                'rastreamento': {'default': []},
                'agent_id': {'required': False},
                'office_id': {'required': False},
                'cliente_id': {'required': False},
                'cidade_id': {'required': False},
                'estado_id': {'required': False},
                'imovel_id': {'required': False},
                'tipo': {'required': False},
            }
        
    def validate(self, attrs):
        if 'agent_id' in attrs:
            agent = Agents.objects.get(agent_id=int(attrs['agent_id']))
            if not agent:
                raise serializers.ValidationError("Agent not found.")
            
        if 'office_id'in attrs:
            office = Offices.objects.get(office_id=int(attrs['office_id']))
            if not office:
                raise serializers.ValidationError("Office not found.")
        
        if 'cliente_id' in attrs:
            cliente = Cliente.objects.get(id=ObjectId(attrs['cliente_id']))
            if not cliente:
                raise serializers.ValidationError("Cliente not found.")
        
        if 'cidade_id' in attrs:
            cidade = City.objects.get(city_id=int(attrs['cidade_id']))
            if not cidade:
                raise serializers.ValidationError("Cidade not found.")
        
        if 'estado_id' in attrs:
            estado = State.objects.get(state_id=int(attrs['estado_id']))
            if not estado:
                raise serializers.ValidationError("Estado not found.")
        
        if 'imovel_id' in attrs:
            imovel = PropertiesNested.objects.get(property_id=int(attrs['imovel_id']))
            if not imovel:
                raise serializers.ValidationError("Imovel not found.")
        
        if 'agent_id' not in attrs and 'office_id' not in attrs:
            raise serializers.ValidationError("Agent or Office is required.")
            
        return super().validate(attrs)
        
    def create(self, validated_data):
        
        validated_data['created_at'] = timezone.now()
        
        if 'agent_id' in validated_data:
            validated_data['agent_id'] = [int(validated_data.pop('agent_id'))]
            
        if 'office_id' in validated_data:
            validated_data['office_id'] = [int(validated_data.pop('office_id'))]
        
        if 'cliente_id' in validated_data:
            validated_data['cliente_id'] = [ObjectId(validated_data.pop('cliente_id'))] 
        
        if 'cidade_id' in validated_data:
            validated_data['cidade_id'] = [int(validated_data.pop('cidade_id'))]
        
        if 'estado_id' in validated_data:
            validated_data['estado_id'] = [int(validated_data.pop('estado_id'))]   
        
        if 'imovel_id' in validated_data:
            validated_data['imovel_id'] = [int(validated_data.pop('imovel_id'))]
        
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
        obj_data['id'] = obj_data.pop('_id')
        
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
 
        return obj
    
    



### Anuncie Serializer ###
class AnuncieReadOnlySerializer(serializers.ModelSerializer):
    
    office_id = OfficeSerializer(many=True, read_only=True)
    bairro_id = NeighborhoodSimpleSerializer(many=True, read_only=True)
    cidade_id = CitySimpleSerializer(many=True, read_only=True)
    estado_id = StateSimpleSerializer(many=True, read_only=True)
    
    class Meta:
        model = Anuncie
        fields = '__all__'

        extra_kwargs = {
                'nome': {'required': True},
                'email': {'required': True},
                'telefone': {'required': True},
                'tipo_imovel': {'required': True},
                'quartos': {'required': True},
                'objetivo': {'required': True},
                'sobre_imovel': {'required': True},
                'office_id': {'required': False},
                'bairro_id': {'required': False},
                'cidade_id': {'required': False},
                'estado_id': {'required': False},
                'created_at': {'required': False},
                'updated_at': {'required': False},
            }



class AnuncieWriteOnlySerializer(serializers.ModelSerializer):
        
    office_id = serializers.CharField()
    bairro_id = serializers.CharField()
    cidade_id = serializers.CharField()
    estado_id = serializers.CharField()
        
    class Meta:
        model = Anuncie
        fields = '__all__'
        extra_kwargs = {
                'nome': {'required': True},
                'email': {'required': True},
                'telefone': {'required': True},
                'tipo_imovel': {'required': True},
                'quartos': {'required': True},
                'objetivo': {'required': True},
                'sobre_imovel': {'required': True},
                'office_id': {'required': False},
                'bairro_id': {'required': False},
                'cidade_id': {'required': False},
                'estado_id': {'required': False},
                'created_at': {'required': False},
                'updated_at': {'required': False},
            }
        
    def validate(self, attrs):
            
        if 'office_id'in attrs:
            office = Offices.objects.get(office_id=int(attrs['office_id']))
            if not office:
                raise serializers.ValidationError("Office not found.")
        
        if 'bairro_id' in attrs:
            bairro = Neighborhood.objects.get(neighborhood_id=int(attrs['bairro_id']))
            if not bairro:
                raise serializers.ValidationError("Bairro not found.")
        
        if 'cidade_id' in attrs:
            cidade = City.objects.get(city_id=int(attrs['cidade_id']))
            if not cidade:
                raise serializers.ValidationError("Cidade not found.")
        
        if 'estado_id' in attrs:
            estado = State.objects.get(state_id=int(attrs['estado_id']))
            if not estado:
                raise serializers.ValidationError("Estado not found.")
        

            
        return super().validate(attrs)
        
    def create(self, validated_data):
        
        validated_data['created_at'] = timezone.now()
        
            
        if 'office_id' in validated_data:
            validated_data['office_id'] = [int(validated_data.pop('office_id'))]
        
        if 'bairro_id' in validated_data:
            validated_data['bairro_id'] = [int(validated_data.pop('bairro_id'))]
        
        if 'cidade_id' in validated_data:
            validated_data['cidade_id'] = [int(validated_data.pop('cidade_id'))]
        
        if 'estado_id' in validated_data:
            validated_data['estado_id'] = [int(validated_data.pop('estado_id'))]   
        
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
        obj_data['id'] = obj_data.pop('_id')
        
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
 
        return obj


# EmailSettings Serializer

class EmailSettingsSerializer(serializers.ModelSerializer):
        
        class Meta:
            model = EmailSettings
            fields = '__all__'
            extra_kwargs = {
                'email': {'required': True},
                'smtp_server': {'required': True},
                'smtp_port': {'required': True},
                'smtp_user': {'required': True},
                'smtp_password': {'required': True},
                'smtp_ssl': {'default': False},
                'smtp_tls': {'default': False},
                'smtp_from': {'required': True},
                'smtp_from_name': {'required': True},
                'smtp_reply_to': {'required': True},
                'smtp_reply_to_name': {'required': True},
                'smtp_test': {'default': False},
                'smtp_test_email': {'required': False},
                'smtp_test_subject': {'required': False},
                'smtp_test_message': {'required': False},
                'header_image': {'required': False},
                'footer_image': {'required': False},
            }
        

class EmailSettingsUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = EmailSettings
        fields = '__all__'
        extra_kwargs = {
            'email': {'required': False},
            'smtp_server': {'required': False},
            'smtp_port': {'required': False},
            'smtp_user': {'required': False},
            'smtp_password': {'required': False},
            'smtp_ssl': {'required': False},
            'smtp_tls': {'required': False},
            'smtp_from': {'required': False},
            'smtp_from_name': {'required': False},
            'smtp_reply_to': {'required': False},
            'smtp_reply_to_name': {'required': False},
            'smtp_test': {'required': False},
            'smtp_test_email': {'required': False},
            'smtp_test_subject': {'required': False},
            'smtp_test_message': {'required': False},
            'header_image': {'required': False},
            'footer_image': {'required': False},
        }
        

"""
class BannerPublicidade(models.Model):
	id = models.ObjectIdField(db_column='_id', primary_key=True, editable=False)
	ordem = models.IntegerField()
	descricao = models.CharField(max_length=255)
	imagem_desktop = models.ImageField(upload_to=upload_path_handler)
	imagem_mobile = models.ImageField(upload_to=upload_path_handler)
	link = models.URLField()
	nova_aba = models.BooleanField()
	status = models.CharField(max_length=255, choices=(('Ativo', 'Ativo'), ('Inativo', 'Inativo')))
	data_inicio = models.DateTimeField()
	data_termino = models.DateTimeField()
	estado_id = models.ArrayReferenceField(to=Estado, on_delete=models.CASCADE, db_column='estado_id')
	cidade_id = models.A
 rayReferenceField(to=Cidade, on_delete=models.CASCADE, db_column='cidade_id')
	created_by = models.ArrayReferenceField(to=Usuario, on_delete=models.CASCADE, related_name='banner_publicidade_created', db_column='created_by')
	updated_by = models.ArrayReferenceField(to=Usuario, on_delete=models.CASCADE, related_name='banner_publicidade_updated', db_column='updated_by')
	created_at = models.DateTimeField(auto_now_add=True, editable=False)
	updated_at = models.DateTimeField(auto_now=True, editable=False)
"""

class BannerPublicidadeReadOnlySerializer(serializers.ModelSerializer):
    
    cidade_id = CitySimpleSerializer(many=True, read_only=True)
    estado_id = StateSimpleSerializer(many=True, read_only=True)
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)

    
    class Meta:
        model = BannerPublicidade
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': False},
            'descricao': {'required': False},
            'imagem_desktop': {'required': False},
            'imagem_mobile': {'required': False},
            'link': {'required': False},
            'nova_aba': {'default': False},
            'status': {'default': 'Ativo'},
            'data_inicio': {'required': False},
            'data_termino': {'required': False},
            'estado_id': {'required': False},
            'cidade_id': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
            'exibir_geral':{'default':False},
            'exibir_todas_cidades_do_estado':{'default':False},
            }
    

class BannerPublicidadeWriteOnlySerializer(serializers.ModelSerializer):
    
    cidade_id = serializers.CharField()
    estado_id = serializers.CharField()
    data_inicio = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", input_formats=["%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%d"])
    data_termino = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", input_formats=["%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%d"])

    class Meta:
        model = BannerPublicidade
        fields = '__all__'
        extra_kwargs = {
            'ordem': {'required': False},
            'descricao': {'required': False},
            'imagem_desktop': {'required': True},
            'imagem_mobile': {'required': True},
            'link': {'required': True},
            'nova_aba': {'default': False},
            'status': {'default': 'Ativo'},
            'data_inicio': {'required': False},
            'data_termino': {'required': False},
            'estado_id': {'required': True},
            'cidade_id': {'required': True},
            'created_by': {'required': False},
            'updated_by': {'required': False},
            'exibir_geral':{'default':False},
            'exibir_todas_cidades_do_estado':{'default':False},
            }
    
    def validate(self, attrs):
        if attrs['exibir_geral'] == False:
        
            if 'estado_id' in attrs:
                estados = str(attrs['estado_id']).replace('[', '').replace(']', '').replace('\'', '').split(',')
                qtd_estados_found = len(list(State.objects.filter(state_id__in=[int(estado) for estado in estados])))
                if len(estados) != qtd_estados_found:
                    raise serializers.ValidationError("Estado not found.")

                if 'cidade_id' in attrs and attrs['exibir_todas_cidades_do_estado'] == False:
                    cidades = str(attrs['cidade_id']).replace('[', '').replace(']', '').replace('\'', '').split(',')
                    cidades_object = list(City.objects.filter(city_id__in=[int(cidade) for cidade in cidades]))
                    # get only estado_id from cidades_object
                    estados_from_cidades = []
                    for cidade in cidades_object:
                        estado_id_list = list(cidade.estado_id)
                        estados_from_cidades.append(str(estado_id_list[0]))
                    estados_from_cidades = list(set(estados_from_cidades))
                    qtd_cidades_found = len(cidades_object)
                    if len(cidades) != qtd_cidades_found:
                        raise serializers.ValidationError("Cidade not found.")
                    # Check if estado_id from cidade is in estado_id from attrs
                    if not all(estado in estados for estado in estados_from_cidades):
                        raise serializers.ValidationError("Some cidades do not belong to the provided estados.")

            if 'cidade_id' in attrs and 'estado_id' not in attrs:
                raise serializers.ValidationError("Estado is required.")
            
        return super().validate(attrs)
        
    
    def create(self, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'imagem_desktop' in self.context['request'].FILES:
                imagem_desktop = self.context['request'].FILES['imagem_desktop']
                validated_data.pop('imagem_desktop')
            if 'imagem_mobile' in self.context['request'].FILES:
                imagem_mobile = self.context['request'].FILES['imagem_mobile']
                validated_data.pop('imagem_mobile')
            
        validated_data['created_by'] = user_id
        validated_data['created_at'] = timezone.now()
            
        ### Cidades ###
        if 'cidade_id' in validated_data:
            cidades = str(validated_data.pop('cidade_id')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['cidade_id'] = [int(cidade) for cidade in cidades]
        
        ### Estados ###
        if 'estado_id' in validated_data:
            estados = str(validated_data.pop('estado_id')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['estado_id'] = [int(estado) for estado in estados]
        
        # Handle the `ordem` field logic during creation
        if 'ordem' not in validated_data or validated_data['ordem'] is None:
            last_ordem = self.Meta.model.objects.order_by('-ordem').first()
            validated_data['ordem'] = last_ordem.ordem + 1 if last_ordem else 1
        else:
            ordem = validated_data['ordem']
            banners_to_update = self.Meta.model.objects.filter(ordem__gte=ordem)
            for banner in banners_to_update:
                banner.ordem += 1
                banner.save()

        # Insert the data into MongoDB
        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
        # Prepare data for the Post instance
        obj_data['id'] = obj_data.pop('_id')
        
        folder_name = "banners_publicidade"
        if 'imagem_desktop' in locals():
            file_url = handle_uploaded_file(file=imagem_desktop, folder_name=folder_name, instance_id=obj_id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'imagem_desktop': file_url}})
        
        if 'imagem_mobile' in locals():
            file_url = handle_uploaded_file(file=imagem_mobile, folder_name=folder_name, instance_id=obj_id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': obj_id}, {'$set': {'imagem_mobile': file_url}})
        
        obj = self.Meta.model(**obj_data)
        
        if obj:
            ## call post_save signal
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=obj, created=True)
 
        return obj

    
    def update(self, instance, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            if 'imagem_desktop' in self.context['request'].FILES:
                imagem_desktop = self.context['request'].FILES['imagem_desktop']
                validated_data.pop('imagem_desktop')
            if 'imagem_mobile' in self.context['request'].FILES:
                imagem_mobile = self.context['request'].FILES['imagem_mobile']
                validated_data.pop('imagem_mobile')

        validated_data['updated_by'] = user_id
        validated_data['updated_at'] = timezone.now()
        
        ### Cidades ###
        if 'cidade_id' in validated_data:
            cidades = str(validated_data.pop('cidade_id')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['cidade_id'] = [int(cidade) for cidade in cidades]
        
        ### Estados ###
        if 'estado_id' in validated_data:
            estados = str(validated_data.pop('estado_id')).replace('[', '').replace(']', '').replace('\'', '').split(',')
            validated_data['estado_id'] = [int(estado) for estado in estados]

        if 'ordem' in validated_data:
            # Handle the `ordem` field logic during update
            new_ordem = validated_data.get('ordem', instance.ordem)
            if new_ordem != instance.ordem:
                if new_ordem > instance.ordem:
                    # Moving the category down in the order
                    banners_to_update = self.Meta.model.objects.filter(ordem__gt=instance.ordem, ordem__lte=new_ordem)
                    for banner in banners_to_update:
                        banner.ordem -= 1
                        banner.save()
                else:
                    # Moving the category up in the order
                    banners_to_update = self.Meta.model.objects.filter(ordem__lt=instance.ordem, ordem__gte=new_ordem)
                    for banner in banners_to_update:
                        banner.ordem += 1
                        banner.save()
                validated_data['ordem'] = new_ordem

        obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
        folder_name = "banners_publicidade"
        if 'imagem_desktop' in locals():
            file_url = handle_uploaded_file(file=imagem_desktop, folder_name=folder_name, instance_id=instance.id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': {'imagem_desktop': file_url}})
        
        if 'imagem_mobile' in locals():
            file_url = handle_uploaded_file(file=imagem_mobile, folder_name=folder_name, instance_id=instance.id)
            if file_url:
                file_update = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': {'imagem_mobile': file_url}})

        if obj:
            from django.db.models.signals import post_save
            post_save.send(sender=self.Meta.model, instance=instance, created=False)
            return instance
        else:
            return None


##############################################
from .utils import OrderedDictField
class QueryParamsUserSerializer(serializers.ModelSerializer):
        
    #user_id = UsuarioSimpleSerializer(many=True, read_only=True)
    user_id =  UsuarioSimpleSerializer(many=True, read_only=True)
    query_params = OrderedDictField()
        
    class Meta:
        model = QueryParamsUser
        fields = '__all__'
        extra_kwargs = {
                'user_id': {'required': True},
                'query_params': {'required': True},
                'origin': {'required': True},
                'url': {'required': False},
                'created_at': {'required': False},
                'updated_at': {'required': False},
            }
    
    
    # def validate(self, attrs):
    #     if 'user_id' in attrs:
    #         user = Usuario.objects.get(id=ObjectId(attrs['user_id']))
            
    #         #only 1 query_params per user
    #         if QueryParamsUser.objects.filter(user_id__in=ObjectId(attrs['user_id'])):
    #             raise serializers.ValidationError("User already has a Search saved.")
            
    #         if not user:
    #             raise serializers.ValidationError("User not found.")
    #     return super().validate(attrs)
    
    # def create(self, validated_data):
        
    #     if 'request' in self.context:
    #         user_id = [ObjectId(self.context['request'].user.id)]

    #     validated_data['user_id'] = user_id
    #     validated_data['created_at'] = timezone.now()
        
    #     obj_id = self.Meta.model.objects.mongo_insert(validated_data)
    #     obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})
        
    #     obj_data['id'] = obj_data.pop('_id')
        
    #     obj = self.Meta.model(**obj_data)
        
    #     if obj:
    #         ## call post_save signal
    #         from django.db.models.signals import post_save
    #         post_save.send(sender=self.Meta.model, instance=obj, created=True)
 
    #     return obj
    
    # def update(self, instance, validated_data):
        
    #     if 'request' in self.context:
    #         user_id = [ObjectId(self.context['request'].user.id)]

    #     validated_data['user'] = user_id
    #     validated_data['updated_at'] = timezone.now()
        
    #     obj = self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set':validated_data})
        
    #     if obj:
    #         from django.db.models.signals import post_save
    #         post_save.send(sender=self.Meta.model, instance=instance, created=False)
    #         return instance
    #     else:
    #         return None



class QueryParamsGeneralSerializer(serializers.ModelSerializer):
    
    query_params = OrderedDictField()
        
    class Meta:
        model = QueryParamsGeneral
        fields = '__all__'
        extra_kwargs = {
                'query_params': {'required': True},
                'origin': {'required': True},
                'url': {'required': False},
                'created_at': {'required': False},
            }
        


##############################################

# class NossaHistoria(models.Model):
# 	"""
# 	NossaHistoria model represents the history of the organization with multilingual support.
# 	Attributes:
# 		id (ObjectIdField): Primary key, non-editable.
# 		ano (PositiveIntegerField): Year of the event.
# 		texto (TextField): Description of the event in Portuguese.
# 		titulo (CharField): Title of the event in Portuguese.
# 		texto_en (TextField): Description of the event in English.
# 		titulo_en (CharField): Title of the event in English.
# 		created_by (ArrayReferenceField): Reference to the user who created the record.
# 		updated_by (ArrayReferenceField): Reference to the user who last updated the record.
# 		created_at (DateTimeField): Timestamp when the record was created, non-editable.
# 		updated_at (DateTimeField): Timestamp when the record was last updated, non-editable.
# 	Meta:
# 		verbose_name (str): Human-readable singular name of the model.
# 		verbose_name_plural (str): Human-readable plural name of the model.
# 		app_label (str): Name of the app the model belongs to.
# 		ordering (list): Default ordering for the model.
# 	"""
    
# 	id = models.ObjectIdField(db_column='_id', primary_key=True, editable=False)
# 	ano = models.PositiveIntegerField()
# 	texto = models.TextField()
# 	titulo = models.CharField(max_length=255)
# 	texto_en = models.TextField()
# 	titulo_en = models.CharField(max_length=255)
# 	created_by = models.ArrayReferenceField(to=Usuario, on_delete=models.CASCADE, related_name='nossa_historia_created', db_column='created_by')
# 	updated_by = models.ArrayReferenceField(to=Usuario, on_delete=models.CASCADE, related_name='nossa_historia_updated', db_column='updated_by')
# 	created_at = models.DateTimeField(auto_now_add=True, editable=False)
# 	updated_at = models.DateTimeField(auto_now=True, editable=False)
	
# 	objects = models.DjongoManager()
	
# 	class Meta:
# 		verbose_name = 'Nossa História'
# 		verbose_name_plural = 'Nossa História'
# 		app_label = 'panel'
# 		ordering = ['ano']

class NossaHistoriaSerializer(serializers.ModelSerializer):
    
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
    
    class Meta:
        model = NossaHistoria
        fields = '__all__'
        extra_kwargs = {
            'ano': {'required': True},
            'texto': {'required': True},
            'titulo': {'required': True},
            'texto_en': {'required': False},
            'titulo_en': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
        }
    
    
    def create(self, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            
        validated_data['created_by'] = user_id
        
        # Handle the 'created_at' field logic during creation
        validated_data['created_at'] = timezone.now()

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj_data.pop('created_by')
        obj = self.Meta.model(**obj_data)
        return obj
    
    
    def update(self, instance, validated_data):
        request = self.context.get('request', None)

        if request and request.user:
            user_id = [ObjectId(request.user.id)]
            validated_data['updated_by'] = user_id

        validated_data['updated_at'] = timezone.now()

        # Update the MongoDB document
        self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': validated_data})

        # Retrieve the updated document
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(instance.id)})

        if not obj_data:
            return None  # Handle case where document is not found after update

        # Convert '_id' to 'id' for Django compatibility
        obj_data['id'] = obj_data.pop('_id')
        
        # Remove the 'created_by' and 'updated_by' fields from the response
        obj_data.pop('created_by')
        obj_data.pop('updated_by')

        # # Get related user instances safely
        # created_by_users = []
        # updated_by_users = []

        # if 'created_by' in obj_data and isinstance(obj_data['created_by'], list) and obj_data['created_by']:
        #     created_by_users = list(Usuario.objects.filter(id__in=obj_data['created_by']))

        # if 'updated_by' in obj_data and isinstance(obj_data['updated_by'], list) and obj_data['updated_by']:
        #     updated_by_users = list(Usuario.objects.filter(id__in=obj_data['updated_by']))

        # # Properly instantiate the NossaHistoria model before returning
        # obj_data.pop('created_by', None)
        # obj_data.pop('updated_by', None)
        
        obj = self.Meta.model(**obj_data)

        # # Ensure `.set()` is only called if the field is an ArrayReferenceField and has values
        # if hasattr(obj, "created_by") and isinstance(obj.created_by, models.QuerySet):
        #     obj.created_by.set(created_by_users if created_by_users else [])

        # if hasattr(obj, "updated_by") and isinstance(obj.updated_by, models.QuerySet):
        #     obj.updated_by.set(updated_by_users if updated_by_users else [])  
        
        # print(f"Updated Object Data: {obj.__dict__}")

        if obj:
            return obj
        else:
            return None





class PaginaSerializer(serializers.ModelSerializer):
    
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
    seo = serializers.SerializerMethodField()
    
    
    class Meta:
        model = Pagina
        fields = '__all__'
        extra_kwargs = {
            'titulo': {'required': True},
            'slug': {'required': True},
            'conteudo': {'required': True},
            'created_by': {'required': False},
            'updated_by': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
        }
    

    def get_seo(self, obj):
        """Retrieve all SEO tags related to this page and group them by city and language."""

        # Ensure obj.id is an ObjectId (Djongo might return it as a string)
        page_id = ObjectId(obj.id) if not isinstance(obj.id, ObjectId) else obj.id

        # Fetch all SEOPagina objects using the correct field: `pagina_id`
        seo_paginas = list(SEOPagina.objects.mongo_find({"pagina_id": page_id}))

        # Print count of retrieved objects for debugging
        #print(f"Number of SEOPagina objects: {len(seo_paginas)}")

        # Dictionary to store SEO tags grouped by cidade and idioma
        seo_data = {}

        for seo_pagina in seo_paginas:
            cidade_nome = "cidade_default"
            idioma = "idioma_default"

            # Convert OrderedDict to dictionary
            seo_pagina = dict(seo_pagina)

            # Convert `_id` to string and remove it
            seo_pagina.pop("_id", None)

            # Extract `cidade_id` list (ArrayReferenceField) and get the first city_id
            cidade_ids = seo_pagina.get("cidade_id", [])
            #print(f"cidade_ids: {cidade_ids}")  # Debugging output

            if isinstance(cidade_ids, list) and cidade_ids:  # Ensure it's a list and not empty
                cidade_id = cidade_ids[0]  # Get the first city_id
                if isinstance(cidade_id, int):  # Query by city_id instead of _id
                    cidade_doc = City.objects.mongo_find_one({"city_id": cidade_id})
                    if cidade_doc:
                        cidade_nome = cidade_doc["city_name"]  # Use city_name instead of ID

            # If `cidade_id` is empty or `None`, set `cidade_default`
            if not cidade_ids:
                cidade_nome = "cidade_default"

            # Fetch idioma
            idioma = seo_pagina.get("idioma", "idioma_default")

            # Convert `seo_tag_id` ObjectId list to full SEO tag details
            seo_tags_data = []
            if "seo_tag_id" in seo_pagina and isinstance(seo_pagina["seo_tag_id"], list):
                seo_tag_ids = seo_pagina["seo_tag_id"]
                seo_tags = list(SEOTag.objects.mongo_find({"_id": {"$in": seo_tag_ids}}))
                for tag in seo_tags:
                    seo_tags_data.append({
                        "titulo": tag.get("titulo", ""),  # Only show SEOTag.titulo
                        "seo_conteudo": seo_pagina.get("seo_conteudo", "")  # Only show SEOPagina.seo_conteudo
                    })

            # Remove unnecessary references before returning
            seo_pagina.pop("pagina_id", None)  # Remove reference to pagina
            seo_pagina.pop("seo_tag_id", None)  # Remove reference to seo_tag_id
            seo_pagina.pop("seo_conteudo", None)  # Remove raw seo_conteudo (it's inside seo_tags_data)

            seo_pagina.pop("created_by", None)
            seo_pagina.pop("created_at", None)
            seo_pagina.pop("updated_by", None)
            seo_pagina.pop("updated_at", None)

            # Organize by cidade and idioma
            if cidade_nome not in seo_data:
                seo_data[cidade_nome] = {}

            if idioma not in seo_data[cidade_nome]:
                seo_data[cidade_nome][idioma] = []

            # Append properly formatted seo_tag objects
            seo_data[cidade_nome][idioma].extend(seo_tags_data)

        return seo_data





    
    def create(self, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            
        validated_data['created_by'] = user_id
        
        # Handle the 'created_at' field logic during creation
        validated_data['created_at'] = timezone.now()

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj_data.pop('created_by')
        obj = self.Meta.model(**obj_data)
        return obj
    
    
    def update(self, instance, validated_data):
        request = self.context.get('request', None)

        if request and request.user:
            user_id = [ObjectId(request.user.id)]
            validated_data['updated_by'] = user_id

        validated_data['updated_at'] = timezone.now()

        # Update the MongoDB document
        self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': validated_data})

        # Retrieve the updated document
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(instance.id)})

        if not obj_data:
            return None  # Handle case where document is not found after update

        # Convert '_id' to 'id' for Django compatibility
        obj_data['id'] = obj_data.pop('_id')
        
        # Remove the 'created_by' and 'updated_by' fields from the response
        obj_data.pop('created_by')
        obj_data.pop('updated_by')
        
        obj = self.Meta.model(**obj_data)

        if obj:
            return obj
        else:
            return None
        


class SEOTagSerializer(serializers.ModelSerializer):
    
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
    
    
    class Meta:
        model = SEOTag
        fields = '__all__'
        extra_kwargs = {
            'titulo': {'required': True},
            'descricao': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
        }
    
    
    def create(self, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            
        validated_data['created_by'] = user_id
        
        # Handle the 'created_at' field logic during creation
        validated_data['created_at'] = timezone.now()

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj_data.pop('created_by')
        obj = self.Meta.model(**obj_data)
        return obj
    
    
    def update(self, instance, validated_data):
        request = self.context.get('request', None)

        if request and request.user:
            user_id = [ObjectId(request.user.id)]
            validated_data['updated_by'] = user_id

        validated_data['updated_at'] = timezone.now()

        # Update the MongoDB document
        self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': validated_data})

        # Retrieve the updated document
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(instance.id)})

        if not obj_data:
            return None  # Handle case where document is not found after update

        # Convert '_id' to 'id' for Django compatibility
        obj_data['id'] = obj_data.pop('_id')
        
        # Remove the 'created_by' and 'updated_by' fields from the response
        obj_data.pop('created_by')
        obj_data.pop('updated_by')
        
        obj = self.Meta.model(**obj_data)

        if obj:
            return obj
        else:
            return None
        



class SEOPaginaSerializer(serializers.ModelSerializer):
    
    pagina = serializers.CharField()
    seo_tag = serializers.CharField()
    cidade = serializers.CharField(required=False)
    created_by = UsuarioSimpleSerializer(many=True, read_only=True)
    updated_by = UsuarioSimpleSerializer(many=True, read_only=True)
     
    class Meta:
        model = SEOPagina
        fields = '__all__'
        extra_kwargs = {
            'seo_conteudo': {'required': False},
            'idioma': {'required': False},
            'pagina': {'required': True},
            'seo_tag': {'required': True},
            'cidade': {'required': False},
            'created_by': {'required': False},
            'updated_by': {'required': False},
            'created_at': {'required': False},
            'updated_at': {'required': False},
        }
    
    def validate(self, attrs):
        
        if 'pagina' in attrs:
            pagina = Pagina.objects.get(id=ObjectId(attrs['pagina']))
            if not pagina:
                raise serializers.ValidationError("Pagina not found.")
            else:
                attrs['pagina'] = [ObjectId(attrs['pagina'])]
        else:
            raise serializers.ValidationError("Pagina is required.")
        
        if 'seo_tag' in attrs:
            seo_tag = SEOTag.objects.get(id=ObjectId(attrs['seo_tag']))
            if not seo_tag:
                raise serializers.ValidationError("SEO Tag not found.")
            else:
                attrs['seo_tag'] = [ObjectId(attrs['seo_tag'])]
        else:
            raise serializers.ValidationError("SEO Tag is required.")
                
        if 'cidade' in attrs:
            cidade = City.objects.get(city_id=int(attrs['cidade']))
            if not cidade:
                raise serializers.ValidationError("Cidade not found.")
            else:
                attrs['cidade'] = [int(attrs['cidade'])]
        else:
            attrs['cidade'] = None
        
        return super().validate(attrs)
    
        
    
    def create(self, validated_data):
        
        if 'request' in self.context:
            user_id = [ObjectId(self.context['request'].user.id)]
            
        validated_data['created_by'] = user_id
        
        
        # Handle the 'created_at' field logic during creation
        validated_data['created_at'] = timezone.now()
        
        # if 'cidade' not in validated_data:
        #     validated_data['cidade'] = []

        obj_id = self.Meta.model.objects.mongo_insert(validated_data)
        
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(obj_id)})

        obj_data['id'] = obj_data.pop('_id')
        obj_data.pop('created_by')
        obj_data['pagina'] = ObjectId(obj_data.pop('pagina')[0])
        obj_data['seo_tag'] = ObjectId(obj_data.pop('seo_tag')[0])
        if obj_data['cidade']:
            obj_data['cidade'] = [int(obj_data['cidade'][0])]
        obj = self.Meta.model(**obj_data)
        return obj
    
    
    def update(self, instance, validated_data):
        request = self.context.get('request', None)

        if request and request.user:
            user_id = [ObjectId(request.user.id)]
            validated_data['updated_by'] = user_id

        validated_data['updated_at'] = timezone.now()

        # Update the MongoDB document
        self.Meta.model.objects.mongo_update_one({'_id': instance.id}, {'$set': validated_data})

        # Retrieve the updated document
        obj_data = self.Meta.model.objects.mongo_find_one({'_id': ObjectId(instance.id)})

        if not obj_data:
            return None  # Handle case where document is not found after update

        # Convert '_id' to 'id' for Django compatibility
        obj_data['id'] = obj_data.pop('_id')
        
        # Remove the 'created_by' and 'updated_by' fields from the response
        obj_data.pop('created_by')
        obj_data.pop('updated_by')
        obj_data['pagina'] = ObjectId(obj_data.pop('pagina')[0])
        obj_data['seo_tag'] = ObjectId(obj_data.pop('seo_tag')[0])
        if obj_data['cidade']:
            obj_data['cidade'] = [int(obj_data['cidade'][0])]
        
        obj = self.Meta.model(**obj_data)

        if obj:
            return obj
        else:
            return None