from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.contrib.auth.models import BaseUserManager
import uuid
from rest_framework.authtoken.models import Token
from django.utils import timezone
from datetime import timedelta

def give_reset_date():
    return timezone.now() + timedelta(days=32)

class UserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError('L\'adresse email est obligatoire')
        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):
        """
            Crée et sauvegarde un superuser avec l'email et le mot de passe donnés.
        """
        if not email:
            raise ValueError('L\'adresse email est obligatoire')
        
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)
        
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)

        return user


class User(AbstractBaseUser, PermissionsMixin):
    class AcademicLevel(models.TextChoices):  # On définit une nouvelle classe à l'intérieur de la classe précédente
        MiddleSchool = 'MS'
        HighSchool = 'HS'
        Seconde = 'S2'
        Premiere = 'P1'
        Terminale = 'T1'
        LicenseDegree = 'LD'
        PreparatoryClass = 'PC'
        DUT_BTS = 'DB'
        bac1 = 'B1'
        bac2 = 'B2'
        bac3 = 'B3'
        bac4 = 'B4'
        bac5 = 'B5'
        bac6 = 'B6'
        MasterDegree = 'MD'
        EngineeringSchool = 'ES'
        BusinessSchool = 'BS'
        DoctorateDegree = 'DD'
        Professional = 'PR'
        default = 'na'

    class AbonnementType(models.TextChoices):
        Free = 'FR'
        Basic = 'BS'
        Review = 'RV'
        BasicWithReview = 'BR' # Si l'utilisateur a un abonnement Basic et qu'il rajoute un abonnement Review, on lui met un abonnement BasicWithReview
        Premium = 'PR'

    username = models.CharField(blank=True, max_length=255, unique=True, null=True)
    firstName = models.CharField(max_length=255, blank=True, null=True, default='')
    lastName = models.CharField(max_length=255, blank=True, null=True, default='')
    email = models.EmailField(unique=True, max_length=255)
    school = models.CharField(max_length=255, blank=True, null=True, default='')
    defaultAcademicLevel = models.CharField(choices=AcademicLevel.choices, max_length=3, default='na')
    # defaultSubjectsStudied = [doit pouvoir contenir une liste d'étiquettes]

    is_active = models.BooleanField(default=True)
    is_abonnement_active = models.BooleanField(default=False) # Permet de savoir si l'abonnement sera renouvelée à la date de fin d'abonnement ou pas. Géré par le webhook.
    subscription_id = models.CharField(max_length=255, blank=True, null=True) # id de l'abonnement Stripe
    
    activated_packs = models.JSONField(blank=True, default=list) # A supprimer

    abonnement_end_date = models.DateTimeField(default=give_reset_date) # Date de fin d'abonnement. Peut être différente de token_reset_date pour les utilisateurs qui ont pris un abonnement sur un an mais qui a une limite de nombre de tokens par mois, géré par webhook
    abonnement_type = models.CharField(choices=AbonnementType.choices, max_length=3, default='FR')
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)

    creationDate = models.DateTimeField(auto_now_add=True)
    modificationDate = models.DateTimeField(auto_now=True)
    publicIdentifier = models.UUIDField(unique=True, editable=False, default=uuid.uuid4)

    packs = models.JSONField(blank=True, default=list) # Liste des packs activés pour l'utilisateur
    
    tokens_used = models.IntegerField(default=0) # Nombre total de tokens utilisés
    tokens_reset_date = models.DateTimeField(default=give_reset_date)
    tokens_limit = models.IntegerField(default=1000000) # Limite de tokens par période
    special_service_used = models.IntegerField(default=0) # Nombre de services spéciaux utilisés

    stripe_id = models.CharField(max_length=255, blank=True, null=True) # customer_id Stripe

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    def __str__(self):
        return self.email

    def generate_auth_token(self):
        """Génère ou récupère un token d'authentification pour l'utilisateur"""
        token, created = Token.objects.get_or_create(user=self)
        return token.key

    @property
    def auth_token(self):
        """Récupère le token actuel de l'utilisateur"""
        try:
            return Token.objects.get(user=self).key
        except Token.DoesNotExist:
            return None

    def save(self, *args, **kwargs):
        if not self.username:
            self.username = self.email.replace('@', '-').replace('.', '-')
        super().save(*args, **kwargs)

