#PortalREMax/accounts
from djongo import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
import random
from django.core.exceptions import ValidationError
from .connection import get_mongo_connection

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}'

# from django.contrib.auth.models import Group

# class AuthGroupPermission(models.Model):
#     """
#     Model to store group-permission relationships in MongoDB.
#     This mimics the structure of Django's auth_group_permissions table.
#     """
#     group_id = models.IntegerField()
#     permission_id = models.IntegerField()

#     objects = models.DjongoManager()

#     class Meta:
#         verbose_name = "Group Permission"
#         verbose_name_plural = "Group Permissions"
#         app_label = "accounts"
#         db_table = "auth_group_permissions"

#     def __str__(self):
#         return f"Group {self.group_id} -> Permission {self.permission_id}"
    
class CustomUserManager(BaseUserManager, models.DjongoManager):
    
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError("The Email field must be set")
        
        # check if email is unique
        db = get_mongo_connection()
        if db.accounts_usuario.find({'email': email}).count() > 0:
            raise ValueError('Email must be unique')

        email = self.normalize_email(email)

        groups = extra_fields.pop("groups", [])  # Extract before passing to model
        permissions = extra_fields.pop("user_permissions", [])  # Extract before passing
        
        # Always set is_active to True for new users
        extra_fields['is_active'] = True

        user = self.model(email=email, **extra_fields)

        if password:
            user.set_password(password)  # ✅ Ensure proper password hashing
        else:
            raise ValueError("The Password field must be set")

        user.save(using=self._db)

        # ✅ Use `.set()` for ManyToMany relationships
        if groups:
            user.groups.set(groups)  
        if permissions:
            user.user_permissions.set(permissions)  

        return user

    def create_superuser(self, email, password=None, **extra_fields):
        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(AbstractUser):
    
    # categoria_choices = (
    #     ('admin', 'Admin'),
	# 	('cliente', 'Cliente'),
	# )
    
    # Map MongoDB's _id to Django's id field
    id = models.ObjectIdField(primary_key=True, db_column='_id')
    
    username = None
    email = models.EmailField(blank=False, null=False)
    is_active = models.BooleanField(default=True)
    bio = models.TextField(blank=True, null=True)
    data_nascimento = models.DateField(blank=True, null=True)
    telefone = models.CharField(max_length=255, blank=True, null=True)
    foto = models.ImageField(blank=True, null=True)
    #categoria = models.CharField(max_length=255, choices=categoria_choices, default='admin')

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = CustomUserManager()
    mongo_objects = models.DjongoManager()


    def __str__(self):
        return self.email
    


    
    class Meta:
        verbose_name = 'Usuario'
        verbose_name_plural = 'Usuarios'
        app_label = 'accounts'




# from v1.models import Neighborhood, City, State
# from rest_framework.authtoken.models import Token
# class Cliente(models.Model):
    
#     # Map MongoDB's _id to Django's id field
#     id = models.ObjectIdField(primary_key=True, db_column='_id')
#     nome = models.CharField(max_length=255)
#     email = models.EmailField(unique=True)
#     password = models.CharField(max_length=255, blank=True, null=True)
#     telefone = models.CharField(max_length=255, blank=True, null=True)
#     data_nascimento = models.DateField(blank=True, null=True)
#     cidade = models.ArrayReferenceField(to=City, to_field="city_id", on_delete=models.CASCADE, blank=True, null=True, related_name='cidade', db_column='cidade_id')
#     bairro = models.ArrayReferenceField(to=Neighborhood, to_field="neighborhood_id", on_delete=models.CASCADE, blank=True, null=True, related_name='bairro', db_column='bairro_id')
#     estado = models.ArrayReferenceField(to=State, to_field="state_id", on_delete=models.CASCADE, blank=True, null=True, related_name='estado', db_column='estado_id')
#     foto = models.ImageField(blank=True, null=True)
#     is_active = models.BooleanField(default=True)
#     created_at = models.DateTimeField(auto_now_add=True)
#     updated_at = models.DateTimeField(auto_now=True)
    
#     @property
#     def is_authenticated(self):
#         """Ensure Cliente is compatible with Django authentication system."""
#         return True  # Since it's an authenticated user, return True
    
#     def set_password(self, raw_password):
#         from django.contrib.auth.hashers import make_password
#         self.password = make_password(raw_password)
        
#     def check_password(self, raw_password):
#         from django.contrib.auth.hashers import check_password
#         return check_password(raw_password, self.password)

#     objects = models.DjongoManager()


#     def __str__(self):
#         return f"{self.nome} - {self.email}"
    
#     class Meta:
#         verbose_name = 'Cliente'
#         verbose_name_plural = 'Clientes'
#         app_label = 'accounts'
#         ordering = ['nome']

from django.contrib.auth.models import AbstractBaseUser
from rest_framework.authtoken.models import Token
from v1.models import Neighborhood, City, State

class Cliente(AbstractBaseUser):
    """
    Custom Cliente model to work with Django's Token Authentication.
    """

    id = models.ObjectIdField(primary_key=True, db_column="_id")
    email = models.EmailField()
    password = models.CharField(max_length=255)
    nome = models.CharField(max_length=255)
    is_active = models.BooleanField(default=True)
    telefone = models.CharField(max_length=255, blank=True, null=True)
    data_nascimento = models.DateField(blank=True, null=True)
    cidade = models.ArrayReferenceField(to=City, to_field="city_id", on_delete=models.CASCADE, blank=True, null=True, related_name='cidade', db_column='cidade_id')
    bairro = models.ArrayReferenceField(to=Neighborhood, to_field="neighborhood_id", on_delete=models.CASCADE, blank=True, null=True, related_name='bairro', db_column='bairro_id')
    estado = models.ArrayReferenceField(to=State, to_field="state_id", on_delete=models.CASCADE, blank=True, null=True, related_name='estado', db_column='estado_id')
    foto = models.ImageField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    USERNAME_FIELD = "email"

    def set_password(self, raw_password):
        from django.contrib.auth.hashers import make_password
        self.password = make_password(raw_password)

    def check_password(self, raw_password):
        from django.contrib.auth.hashers import check_password
        return check_password(raw_password, self.password)

    def __str__(self):
        return f"{self.nome} - {self.email}"
    
    objects = models.DjongoManager()

    class Meta:
        verbose_name = "Cliente"
        verbose_name_plural = "Clientes"
        app_label = "accounts"

        
from rest_framework_simplejwt.tokens import RefreshToken

class ClienteToken(models.Model):
    id = models.ObjectIdField(primary_key=True, db_column="_id")  # MongoDB `_id`
    key = models.CharField(max_length=512, unique=True)  # Stores JWT Token
    cliente = models.ForeignKey("Cliente", on_delete=models.CASCADE, related_name="tokens")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Token for {self.cliente.email}"

    @staticmethod
    def create_token(cliente):
        """ Generate a JWT and store it in MongoDB manually """
        refresh = RefreshToken()
        refresh["sub"] = str(cliente.id)  # ✅ Store Cliente ID in JWT payload
        refresh["email"] = cliente.email  # ✅ Store email in JWT payload
        access_token = str(refresh.access_token)

        # Store token in MongoDB
        token = ClienteToken.objects.create(cliente=cliente, key=access_token)
        return token
    
    

from django.contrib.auth import get_user_model

User = get_user_model()

class UserActionLog(models.Model):
    id = models.ObjectIdField(primary_key=True, db_column='_id')
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    action = models.CharField(max_length=255)  # Example: 'login', 'logout', 'view_page'
    path = models.CharField(max_length=500)    # Requested URL path
    method = models.CharField(max_length=10)   # HTTP Method (GET, POST, etc.)
    timestamp = models.DateTimeField(auto_now_add=True)
    ip_address = models.GenericIPAddressField(null=True, blank=True)

    class Meta:
        verbose_name = 'User Action Log'
        verbose_name_plural = 'User Action Logs'
        ordering = ['-timestamp']

    def __str__(self):
        return f"{self.user.email} - {self.action} at {self.timestamp}"
