from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
import secrets
import string
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.conf import settings

# Create your models here.

# Ta klasa reprezentuje użytkownika w systemie. Dziedziczy po AbstractUser, co pozwala na rozszerzenie domyślnej funkcjonalności użytkownika Django.
class User(AbstractUser):
    ROLES = (
        ('admin', 'Admin'),
        ('moderator', 'Moderator'),
        ('user', 'User'),
    )
    role = models.CharField(max_length=10, choices=ROLES, default='user')
    avatar_image = models.ImageField(upload_to='avatars/', null=True, blank=True)
    username = models.CharField(max_length=150, unique=True)
    bio = models.TextField(blank=True, default='')
    token_version = models.IntegerField(default=0)
    # Add related_name to resolve clashes
    groups = models.ManyToManyField(
        'auth.Group',
        related_name='custom_user_set',
        blank=True,
        help_text='The groups this user belongs to.',
        verbose_name='groups',
    )
    user_permissions = models.ManyToManyField(
        'auth.Permission',
        related_name='custom_user_set',
        blank=True,
        help_text='Specific permissions for this user.',
        verbose_name='user permissions',
    )


    def __str__(self):
        return self.username

# Ta klasa obsługuje tokeny resetowania hasła, które są używane do weryfikacji użytkowników podczas procesu resetowania hasła.
class PasswordResetToken(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    token = models.CharField(max_length=100, unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
    expires_at = models.DateTimeField()
    used = models.BooleanField(default=False)

    def save(self, *args, **kwargs):
        if not self.token:
            # Generate a random token
            alphabet = string.ascii_letters + string.digits
            self.token = ''.join(secrets.choice(alphabet) for _ in range(64))
        super().save(*args, **kwargs)

#Ta funkcja sprawdza, czy token jest ważny. Token jest ważny, jeśli nie został użyty i nie wygasł.
    def is_valid(self):
        return (
            not self.used and
            self.expires_at > timezone.now()
        )

    class Meta:
        verbose_name = 'Password Reset Token'
        verbose_name_plural = 'Password Reset Tokens'

class EmailChangeToken(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    new_email = models.EmailField()
    token = models.CharField(max_length=100, unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
    expires_at = models.DateTimeField()
    used = models.BooleanField(default=False)

    def save(self, *args, **kwargs):
        if not self.token:
            import secrets, string
            alphabet = string.ascii_letters + string.digits
            self.token = ''.join(secrets.choice(alphabet) for _ in range(64))
        super().save(*args, **kwargs)

    def is_valid(self):
        from django.utils import timezone
        return (not self.used) and (self.expires_at > timezone.now())

class Favorite(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='favorites'
    )
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=['user', 'content_type', 'object_id'],
                name='uniq_favorite_per_user_object'
            )
        ]
        indexes = [
            models.Index(fields=['user', 'content_type']),
            models.Index(fields=['content_type', 'object_id']),
        ]

    def __str__(self):
        return f'{self.user} ♥ {self.content_type.app_label}.{self.content_type.model}:{self.object_id}'