from django.contrib.auth.models import AbstractUser
from django.db import models
from django.conf import settings

class User(AbstractUser):
    class Role(models.TextChoices):
        ADMIN = "ADMIN", "Admin"
        TEACHER = "TEACHER", "Teacher"
        STUDENT = "STUDENT", "Student"

    role = models.CharField(max_length=16, choices=Role.choices, default=Role.STUDENT)
    pref_language = models.CharField(max_length=8, default="en")
    pref_theme = models.CharField(max_length=8, default="light")

    def __str__(self):
        return self.username

    @property
    def is_admin(self): return self.role == self.Role.ADMIN
    @property
    def is_teacher(self): return self.role == self.Role.TEACHER
    @property
    def is_student(self): return self.role == self.Role.STUDENT

    def save(self, *args, **kwargs):
        # Keep admins/superusers as staff so they always see Django admin
        if self.is_superuser or self.role == self.Role.ADMIN:
            self.is_staff = True
        super().save(*args, **kwargs)


class SecurityLog(models.Model):
    ACTION_CHOICES = [
        ("HONEYPOT_HIT", "Honeypot hit"),
        ("FAILED_LOGIN", "Failed login"),
        ("BLOCKED", "Blocked"),
        ("RATE_LIMIT", "Rate limited"),
        # Added these two so your views.py logic is fully supported:
        ("WRONG_PORTAL_ROLE", "Wrong portal role"),
        ("INVALID_INVITE_TOKEN", "Invalid invite token"),
    ]

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL
    )
    ip = models.GenericIPAddressField(null=True, blank=True)
    path = models.CharField(max_length=512)
    action = models.CharField(max_length=32, choices=ACTION_CHOICES)
    user_agent = models.TextField(blank=True)
    meta = models.JSONField(default=dict, blank=True)

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        indexes = [
            models.Index(fields=["action", "created_at"]),
            models.Index(fields=["ip", "created_at"]),
        ]
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.action} {self.ip} {self.path} @ {self.created_at:%Y-%m-%d %H:%M:%S}"
        
        
# ==========================================
# REGISTRATION SETTINGS (The Code)
# ==========================================
class RegistrationSetting(models.Model):
    code = models.CharField(
        max_length=50, 
        default="k5gg43lq", 
        help_text="The secret code users must enter to sign up."
    )
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "Registration Setting (Invite Code)"
        verbose_name_plural = "Registration Settings"

    def __str__(self):
        return f"Current Code: {self.code}"

    @classmethod
    def get_code(cls):
        """Helper to get the current code, creating it if missing."""
        # This ensures there is always only one record (ID=1)
        obj, created = cls.objects.get_or_create(pk=1)
        return obj.code

    def save(self, *args, **kwargs):
        self.pk = 1  # Force this to always be the first record (Singleton)
        super().save(*args, **kwargs)