from django.contrib.auth.models import AbstractUser
from django.db import models


class User(AbstractUser):
    display_name = models.CharField(max_length=150, blank=True)
    force_password_change = models.BooleanField(default=False)
    last_password_change_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.display_name or self.get_full_name() or self.username


class UserCompanyAccess(models.Model):
    """Explicit tenant/company membership for privileged and operational users.

    Django superusers remain global emergency administrators. Every non-superuser
    must be associated with one or more companies through this table (or, during
    migration only, through their employee profile as a compatibility fallback).
    """

    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="company_accesses")
    company = models.ForeignKey("organization.Company", on_delete=models.CASCADE, related_name="user_accesses")
    is_default = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=["user", "company"], name="uq_user_company_access"),
        ]
        indexes = [models.Index(fields=["user", "is_active"])]

    def __str__(self):
        return f"{self.user} / {self.company}"


class LoginAttempt(models.Model):
    """Small database-backed login throttle. No password or sensitive credential is stored."""

    username = models.CharField(max_length=150)
    ip_address = models.GenericIPAddressField(default="0.0.0.0")
    failure_count = models.PositiveIntegerField(default=0)
    first_failed_at = models.DateTimeField(null=True, blank=True)
    blocked_until = models.DateTimeField(null=True, blank=True, db_index=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=["username", "ip_address"], name="uniq_login_attempt_user_ip"),
        ]
        indexes = [models.Index(fields=["username", "updated_at"])]

    def __str__(self):
        return f"{self.username}@{self.ip_address or 'unknown'} ({self.failure_count})"
