from djongo import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.contrib.auth.hashers import make_password, check_password
import random


# def upload_path_handler(instance, filename):
#     class_name = instance.__class__.__name__.lower()
#     return f'files/{class_name}s/fotos/{instance.id}/{filename}'

def upload_path_handler(instance, filename):
	class_name = instance.__class__.__name__.lower()
	if not instance.id:
		instance.id = random.randint(10000000, 99999999)
	return f'{class_name}s/img/{instance.id}/{filename}'


class Nivel(models.Model):
    id = models.ObjectIdField(db_column='_id', primary_key=True, editable=False)
    name = models.CharField(max_length=255)
    permissions = models.JSONField(default=list, blank=True)
    
    objects = models.DjongoManager()
    
    class Meta:
        verbose_name = 'Nivel'
        verbose_name_plural = 'Niveis'
        app_label = 'accounts'
    
    def __str__(self):
        permissions_str = ', '.join([f"{perm['app_label']}.{perm['codename']}" for perm in self.permissions])
        return f"{self.name} - {permissions_str}"


class CustomUserManager(BaseUserManager, models.DjongoManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('User must have an email address')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        #user.set_password(password)
        user.save(using=self._db)
        return user
    
    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_active', True)
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        
        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')
        return self.create_user(email, password, **extra_fields)
    



class Usuario(AbstractBaseUser):
    
    categoria_choices = (
        ('admin', 'Admin'),
		('cliente', 'Cliente'),
	)
    id = models.ObjectIdField(db_column='_id', primary_key=True, editable=False)
    first_name = models.CharField(max_length=255, blank=True, null=True)
    last_name = models.CharField(max_length=255, blank=True, null=True)
    password = models.CharField(max_length=255, blank=False, null=False)
    email = models.EmailField(unique=True, default='email', blank=False, null=False)
    telefone = models.CharField(max_length=255, blank=True, null=True)
    foto = models.ImageField(upload_to=upload_path_handler, blank=True, null=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=True)
    is_superuser = models.BooleanField(default=False)
    nivel = models.ArrayReferenceField(to=Nivel, on_delete=models.CASCADE, blank=True, null=True)
    categoria = models.CharField(max_length=255, choices=categoria_choices, default='admin')
    
    class Meta:
        verbose_name = 'Usuario'
        verbose_name_plural = 'Usuarios'
        app_label = 'accounts'
    
    def __str__(self):
        return self.email 	
    
    def has_perm(self, perm, obj=None):
        if self.is_staff:
            return True
        if self.nivel and self.nivel.permissions.filter(codename=perm).exists():
            return True
        return False

    def has_module_perms(self, app_label):
        return True
    
    def set_password(self, raw_password):
        self.password = make_password(raw_password)

    def save(self, *args, **kwargs):
        # Hash the password if it's being updated and isn't already hashed
        if not self.pk or 'password' in self.get_deferred_fields() or self._password_needs_hashing():
            self.set_password(self.password)
        super().save(*args, **kwargs)

    def _password_needs_hashing(self):
        # Simple check if the password field needs hashing
        return not self.password.startswith('pbkdf2_')

    def check_password(self, raw_password):
        return check_password(raw_password, self.password)
	
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []
    
    objects = CustomUserManager()
    
    # def save(self, *args, **kwargs):
    #     if not self.id:
    #         #print("Handle Initial")
    #         self._handle_initial_save()
    #     else:
    #         #print("Handle Existing")
    #         self._handle_existing_save()

    #     super().save(*args, **kwargs)

    # def _handle_initial_save(self):
    #     """Handle saving for new instances, setting the foto to None first."""
    #     if self.foto:
    #         foto = self.foto
    #         self.foto = None
    #     super(Usuario, self).save(force_insert=True)
    #     if self.foto:
    #         self.foto = foto
    #         self.save(update_fields=['foto'])

    # def _handle_existing_save(self):
    #     """Handle saving for existing instances, ensuring password hashing."""
    #     try:
    #         obj = Usuario.objects.get(pk=self.pk)
    #         # Check if the password has been changed
    #         if self.password != obj.password:
    #             self.password = make_password(self.password)
    #         else:
    #             self.password = obj.password
    #     except Usuario.DoesNotExist:
    #         pass