"""
User models for ThrillWiki.
Custom user model with OAuth and MFA support.
"""

import uuid
from django.contrib.auth.models import AbstractUser
from django.db import models
from apps.core.models import BaseModel


class User(AbstractUser):
    """
    Custom user model with UUID primary key and additional fields.
    
    Supports:
    - Email-based authentication
    - OAuth (Google, Discord)
    - Two-factor authentication (TOTP)
    - User reputation and moderation
    """
    
    # Override id to use UUID
    id = models.UUIDField(
        primary_key=True,
        default=uuid.uuid4,
        editable=False
    )
    
    # Email as primary identifier
    email = models.EmailField(
        unique=True,
        help_text="Email address for authentication"
    )
    
    # OAuth fields
    oauth_provider = models.CharField(
        max_length=50,
        blank=True,
        choices=[
            ('', 'None'),
            ('google', 'Google'),
            ('discord', 'Discord'),
        ],
        help_text="OAuth provider used for authentication"
    )
    oauth_sub = models.CharField(
        max_length=255,
        blank=True,
        help_text="OAuth subject identifier from provider"
    )
    
    # MFA fields
    mfa_enabled = models.BooleanField(
        default=False,
        help_text="Whether two-factor authentication is enabled"
    )
    
    # Profile fields
    avatar_url = models.URLField(
        blank=True,
        help_text="URL to user's avatar image"
    )
    bio = models.TextField(
        blank=True,
        max_length=500,
        help_text="User biography"
    )
    
    # Moderation fields
    banned = models.BooleanField(
        default=False,
        db_index=True,
        help_text="Whether this user is banned"
    )
    ban_reason = models.TextField(
        blank=True,
        help_text="Reason for ban"
    )
    banned_at = models.DateTimeField(
        null=True,
        blank=True,
        help_text="When the user was banned"
    )
    banned_by = models.ForeignKey(
        'self',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='users_banned',
        help_text="Moderator who banned this user"
    )
    
    # Reputation system
    reputation_score = models.IntegerField(
        default=0,
        help_text="User reputation score based on contributions"
    )
    
    # Timestamps (inherited from AbstractUser)
    # date_joined, last_login
    
    # Use email for authentication
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']
    
    class Meta:
        db_table = 'users'
        ordering = ['-date_joined']
        indexes = [
            models.Index(fields=['email']),
            models.Index(fields=['banned']),
        ]
    
    def __str__(self):
        return self.email
    
    def ban(self, reason, banned_by=None):
        """Ban this user"""
        from django.utils import timezone
        self.banned = True
        self.ban_reason = reason
        self.banned_at = timezone.now()
        self.banned_by = banned_by
        self.save(update_fields=['banned', 'ban_reason', 'banned_at', 'banned_by'])
    
    def unban(self):
        """Unban this user"""
        self.banned = False
        self.ban_reason = ''
        self.banned_at = None
        self.banned_by = None
        self.save(update_fields=['banned', 'ban_reason', 'banned_at', 'banned_by'])
    
    @property
    def display_name(self):
        """Return the user's display name (full name or username)"""
        if self.first_name or self.last_name:
            return f"{self.first_name} {self.last_name}".strip()
        return self.username or self.email.split('@')[0]


class UserRole(BaseModel):
    """
    User role assignments for permission management.
    
    Roles:
    - user: Standard user (default)
    - moderator: Can approve submissions and moderate content
    - admin: Full access to admin features
    """
    
    ROLE_CHOICES = [
        ('user', 'User'),
        ('moderator', 'Moderator'),
        ('admin', 'Admin'),
    ]
    
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name='role'
    )
    role = models.CharField(
        max_length=20,
        choices=ROLE_CHOICES,
        default='user',
        db_index=True
    )
    granted_at = models.DateTimeField(auto_now_add=True)
    granted_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='roles_granted'
    )
    
    class Meta:
        db_table = 'user_roles'
    
    def __str__(self):
        return f"{self.user.email} - {self.role}"
    
    @property
    def is_moderator(self):
        """Check if user is a moderator or admin"""
        return self.role in ['moderator', 'admin']
    
    @property
    def is_admin(self):
        """Check if user is an admin"""
        return self.role == 'admin'


class UserProfile(BaseModel):
    """
    Extended user profile information.
    
    Stores additional user preferences and settings.
    """
    
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name='profile'
    )
    
    # Preferences
    email_notifications = models.BooleanField(
        default=True,
        help_text="Receive email notifications"
    )
    email_on_submission_approved = models.BooleanField(
        default=True,
        help_text="Email when submissions are approved"
    )
    email_on_submission_rejected = models.BooleanField(
        default=True,
        help_text="Email when submissions are rejected"
    )
    
    # Privacy
    profile_public = models.BooleanField(
        default=True,
        help_text="Make profile publicly visible"
    )
    show_email = models.BooleanField(
        default=False,
        help_text="Show email on public profile"
    )
    
    # Statistics
    total_submissions = models.IntegerField(
        default=0,
        help_text="Total number of submissions made"
    )
    approved_submissions = models.IntegerField(
        default=0,
        help_text="Number of approved submissions"
    )
    
    class Meta:
        db_table = 'user_profiles'
    
    def __str__(self):
        return f"Profile for {self.user.email}"
    
    def update_submission_stats(self):
        """Update submission statistics"""
        from apps.moderation.models import ContentSubmission
        self.total_submissions = ContentSubmission.objects.filter(user=self.user).count()
        self.approved_submissions = ContentSubmission.objects.filter(
            user=self.user,
            status='approved'
        ).count()
        self.save(update_fields=['total_submissions', 'approved_submissions'])
