
# PortalREMax/accounts/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Usuario, Cliente
import os
from django.conf import settings
from django.db import transaction
from bson import ObjectId
from django.core.files.storage import default_storage


def save_uploaded_file(instance, file_field, base_folder):
    if not file_field:
        return

    instance_id = instance.id
    file_name = os.path.basename(file_field.name)
    relative_path = os.path.join(base_folder, 'img', str(instance_id), file_name)

    # In development, ensure local folder exists
    if not settings.USE_S3:
        full_path = os.path.join(settings.MEDIA_ROOT, relative_path)
        os.makedirs(os.path.dirname(full_path), exist_ok=True)

    # Save or overwrite file using default_storage
    file_field.name = default_storage.save(relative_path, file_field)

    return relative_path


@receiver(post_save, sender=Usuario)
def save_usuario(sender, instance, created, **kwargs):
    if created and instance.foto:
        path = save_uploaded_file(instance, instance.foto, "accounts/usuarios")
        if path:
            instance.foto.name = path
            with transaction.atomic():
                instance.save(update_fields=['foto'])


@receiver(post_save, sender=Cliente)
def save_cliente(sender, instance, created, **kwargs):
    if created and instance.foto:
        path = save_uploaded_file(instance, instance.foto, "accounts/clientes")
        if path:
            instance.foto.name = path
            instance.save(update_fields=['foto'])


@receiver(post_save, sender=Usuario)
def update_usuario(sender, instance, created, **kwargs):
    if not created and instance.foto:
        file_name = os.path.basename(instance.foto.name)
        expected_path = os.path.join("accounts/usuarios", 'img', str(instance.id), file_name)

        if instance.foto.name != expected_path:
            path = save_uploaded_file(instance, instance.foto, "accounts/usuarios")
            if path:
                instance.foto.name = path
                instance.save(update_fields=['foto'])


@receiver(post_save, sender=Cliente)
def update_cliente(sender, instance, created, **kwargs):
    if not created and instance.foto:
        file_name = os.path.basename(instance.foto.name)
        expected_path = os.path.join("accounts/clientes", 'img', str(instance.id), file_name)

        if instance.foto.name != expected_path:
            path = save_uploaded_file(instance, instance.foto, "accounts/clientes")
            if path:
                instance.foto.name = path
                instance.save(update_fields=['foto'])

# @receiver(post_save, sender=Usuario)
# def save_usuario(sender, instance, created, **kwargs):
#     if created and instance.foto:
#         instance_id = instance.id
#         file_name = os.path.basename(instance.foto.name)
#         media_root = settings.MEDIA_ROOT
#         new_path = os.path.join(media_root, f'accounts/usuarios/img/{instance_id}/{file_name}')
        
#         # Ensure the directory exists
#         os.makedirs(os.path.dirname(new_path), exist_ok=True)
        
#         # Save the file to the new path
#         with open(new_path, 'wb') as f:
#             for chunk in instance.foto.chunks():
#                 f.write(chunk)
        
#         # Update the instance's foto field to the new path
#         instance.foto.name = new_path
#         with transaction.atomic():
#             instance.save()

# @receiver(post_save, sender=Cliente)
# def save_cliente(sender, instance, created, **kwargs):
#     if created and instance.foto:
#         instance_id = instance.id
#         file_name = os.path.basename(instance.foto.name)
#         media_root = settings.MEDIA_ROOT
#         new_path = os.path.join(media_root, f'accounts/clientes/img/{instance_id}/{file_name}')
        
#         # Ensure the directory exists
#         os.makedirs(os.path.dirname(new_path), exist_ok=True)
        
#         # Save the file to the new path
#         with open(new_path, 'wb') as f:
#             for chunk in instance.foto.chunks():
#                 f.write(chunk)
        
#         # Update the instance's foto field to the new path
#         instance.foto.name = new_path
#         instance.save()
        

# @receiver(post_save, sender=Usuario)
# def update_usuario(sender, instance, created, **kwargs):
#     if not created and instance.foto:
#         instance_id = instance.id
#         file_name = os.path.basename(instance.foto.name)
#         file_path = f"accounts/usuarios/img/{instance_id}/{file_name}"
#         media_root = settings.MEDIA_ROOT
#         new_path = os.path.join(media_root, file_path)
        
#         # Ensure the directory exists
#         os.makedirs(os.path.dirname(new_path), exist_ok=True)
        
#         # Save the file to the new path
#         with open(new_path, 'wb') as f:
#             for chunk in instance.foto.chunks():
#                 f.write(chunk)
        
#         # Update the instance's foto field only if it hasn't been updated
#         if instance.foto.name != file_path:
#             instance.foto.name = file_path
#             instance.save(update_fields=['foto'])  # Avoid triggering full save


# @receiver(post_save, sender=Cliente)
# def update_cliente(sender, instance, created, **kwargs):
#     if not created and instance.foto:
#         instance_id = instance.id
#         file_name = os.path.basename(instance.foto.name)
#         file_path = f"accounts/clientes/img/{instance_id}/{file_name}"
#         media_root = settings.MEDIA_ROOT
#         new_path = os.path.join(media_root, file_path)
        
#         # Ensure the directory exists
#         os.makedirs(os.path.dirname(new_path), exist_ok=True)
        
#         # Save the file to the new path
#         with open(new_path, 'wb') as f:
#             for chunk in instance.foto.chunks():
#                 f.write(chunk)
        
#         # Update the instance's foto field only if it hasn't been updated
#         if instance.foto.name != file_path:
#             instance.foto.name = file_path
#             instance.save(update_fields=['foto'])  # Avoid triggering full save
            



from django.contrib.auth.signals import user_logged_in, user_logged_out
from .models import UserActionLog

@receiver(user_logged_in)
def log_user_login(sender, request, user, **kwargs):
    UserActionLog.objects.create(
        user=user,
        action='login',
        path=request.path,
        method='POST',
        ip_address=request.META.get('REMOTE_ADDR')
    )

@receiver(user_logged_out)
def log_user_logout(sender, request, user, **kwargs):
    UserActionLog.objects.create(
        user=user,
        action='logout',
        path=request.path,
        method='POST',
        ip_address=request.META.get('REMOTE_ADDR')
    )


# # from rest_framework_simplejwt.tokens import OutstandingToken
# # from pymongo import MongoClient

# # from django.db.models.signals import post_save
# # from django.dispatch import receiver
# from rest_framework_simplejwt.tokens import OutstandingToken, BlacklistedToken, AccessToken
# from pymongo import MongoClient
# # from django.conf import settings

# @receiver(post_save, sender=OutstandingToken)
# def save_token_in_mongodb(sender, instance, **kwargs):
#     """ 🔥 Manually store JWT tokens in MongoDB """
#     client = MongoClient(settings.DATABASES["default"]["CLIENT"]["host"])
#     db = client[settings.DATABASES["default"]["NAME"]]
#     outstanding_tokens = db.token_blacklist_outstandingtoken
    
#     print("Here 1")

#     # 🔎 Check if token is already in DB
#     if not outstanding_tokens.find_one({"jti": instance.jti}):
#         outstanding_tokens.insert_one({
#             "jti": instance.jti,
#             "token_type": instance.token_type,
#             "created_at": instance.created_at,
#         })

# @receiver(post_save, sender=AccessToken)
# def save_access_token(sender, instance, **kwargs):
#     """ 🔥 Manually store access tokens (since they are not stored by default) """
#     client = MongoClient(settings.DATABASES["default"]["CLIENT"]["host"])
#     db = client[settings.DATABASES["default"]["NAME"]]
#     outstanding_tokens = db.token_blacklist_outstandingtoken

#     # 🔎 Extract token details
#     jti = instance["jti"]
#     token_type = "access"

#     print("Here 2")
    
#     # 🔎 Check if token already exists
#     if not outstanding_tokens.find_one({"jti": jti}):
#         outstanding_tokens.insert_one({
#             "jti": jti,
#             "token_type": token_type,
#         })
