"""Authentication credentials are separate from wallets and sporting identity."""
import uuid
from django.db import models
from django.db.models import Q


class AccountSecurity(models.Model):
    user = models.OneToOneField('users.User', primary_key=True, on_delete=models.CASCADE, related_name='security_settings')
    totp_secret = models.TextField(blank=True, default='')  # Fernet ciphertext only
    totp_enabled = models.BooleanField(default=False)
    last_totp_counter = models.BigIntegerField(default=-1)
    recovery_hashes = models.JSONField(default=list)
    failed_attempts = models.PositiveSmallIntegerField(default=0)
    locked_until = models.DateTimeField(null=True)


class AccountSession(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, related_name='device_sessions')
    method = models.CharField(max_length=20, default='PASSWORD')
    user_agent = models.CharField(max_length=350, blank=True)
    ip_address = models.GenericIPAddressField(null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    last_seen_at = models.DateTimeField(auto_now_add=True)
    expires_at = models.DateTimeField()
    revoked_at = models.DateTimeField(null=True)

    class Meta:
        indexes = [models.Index(fields=['user','revoked_at','expires_at'], name='user_session_active_idx')]


class AuthChallenge(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, null=True)
    auth_version = models.UUIDField(null=True)
    purpose = models.CharField(max_length=30)
    payload = models.JSONField(default=dict)
    created_at = models.DateTimeField(auto_now_add=True)
    expires_at = models.DateTimeField()
    attempts = models.PositiveSmallIntegerField(default=0)
    consumed_at = models.DateTimeField(null=True)


class PasskeyCredential(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, related_name='passkeys')
    credential_id = models.CharField(max_length=1400, unique=True)
    public_key = models.BinaryField()
    sign_count = models.PositiveBigIntegerField(default=0)
    name = models.CharField(max_length=80, default='Passkey')
    rp_id = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=True)
    last_used_at = models.DateTimeField(null=True)


class LoginIdentity(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey('users.User', on_delete=models.CASCADE, related_name='login_identities')
    provider = models.CharField(max_length=16, choices=[('GOOGLE','Google'),('PHONE','Phone'),('SOLANA','Solana')])
    subject = models.CharField(max_length=255)
    label = models.CharField(max_length=120, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    last_used_at = models.DateTimeField(null=True)

    class Meta:
        constraints = [models.UniqueConstraint(fields=['provider','subject'], name='user_identity_provider_subject'),
                       models.UniqueConstraint(fields=['user','provider'], condition=Q(provider='PHONE'), name='user_one_phone_identity')]


class AccountDeletionRequest(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    user = models.ForeignKey('users.User', on_delete=models.PROTECT, related_name='deletion_requests')
    status = models.CharField(max_length=16, default='PENDING', choices=[('PENDING','Pending review'),('CANCELLED','Cancelled'),('COMPLETED','Completed')])
    reason = models.CharField(max_length=500, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    eligible_after = models.DateTimeField()
    resolved_at = models.DateTimeField(null=True)

    class Meta:
        constraints = [models.UniqueConstraint(fields=['user'], condition=Q(status='PENDING'), name='user_one_pending_deletion')]
