# -*- coding: utf-8 -*-
"""
Accounts Models Module

This module contains all user-related models including:
- Custom User model with extended functionality
- Role model for dynamic role management
- Permission model for granular access control
- Profile model for additional user information

"""

from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.core.validators import RegexValidator
from django.utils.translation import gettext_lazy as _
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import AbstractUser, Permission

from apps.common.models import BaseModel, TimeStampedModel



class Role(BaseModel):
    """
    Role model for dynamic role management.
    
    This model allows creating custom roles with specific permissions
    that can be assigned to users for flexible access control.
    """
    
    # Role identification fields
    name = models.CharField(
        max_length=100, 
        unique=True,
        verbose_name=_("Role Name"),
        help_text=_("Unique name for the role")
    )
    
    # Role description for better understanding
    description = models.TextField(
        blank=True,
        verbose_name=_("Description"),
        help_text=_("Detailed description of the role")
    )
    
    # Role permissions - many-to-many relationship with Django's Permission model
    permissions = models.ManyToManyField(
        Permission,
        blank=True,
        verbose_name=_("Permissions"),
        help_text=_("Specific permissions for this role")
    )
    
    # Role status - whether the role is active or not
    is_active = models.BooleanField(
        default=True,
        verbose_name=_("Is Active"),
        help_text=_("Whether this role is currently active")
    )
    
    # Role priority for hierarchical access control
    priority = models.PositiveIntegerField(
        default=0,
        verbose_name=_("Priority"),
        help_text=_("Higher number means higher priority")
    )

    class Meta:
        verbose_name = _("Role")
        verbose_name_plural = _("Roles")
        ordering = ['-priority', 'name']
        db_table = 'accounts_role'

    def __str__(self):
        """String representation of the role."""
        return f"{self.name} (Priority: {self.priority})"
    
    def get_permissions_list(self):
        """Get list of permission names for this role."""
        return list(self.permissions.values_list('codename', flat=True))
    
    def has_permission(self, permission_codename):
        """Check if role has specific permission."""
        return self.permissions.filter(codename=permission_codename).exists()


class User(AbstractUser, BaseModel):
    """
    Custom User model extending Django's AbstractUser.
    
    This model provides additional fields and functionality
    for comprehensive user management including roles and profiles.
    """
    
    # Enhanced email field - required and unique
    email = models.EmailField(
        _('Email Address'),
        unique=True, 
        help_text=_("User's email address - used for login")
    )
    
    # Phone number with validation
    phone_regex = RegexValidator(
        regex=r'^\+?1?\d{9,15}$',
        message=_("Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
    )
    phone_number = models.CharField(
        _('Phone Number'),
        validators=[phone_regex],
        max_length=17,
        blank=True, 
        null=True,
        help_text=_("User's phone number")
    )
    
    # User roles - many-to-many relationship with Role model
    roles = models.ManyToManyField(
        Role,
        blank=True,
        verbose_name=_("User Roles"),
        help_text=_("Roles assigned to this user")
    )
    
    # Account status fields
    is_verified = models.BooleanField(
        default=False,
        verbose_name=_("Is Verified"),
        help_text=_("Whether the user's email is verified")
    )
    
    # Account activity tracking
    last_login_ip = models.GenericIPAddressField(
        null=True,
        blank=True,
        verbose_name=_("Last Login IP"),
        help_text=_("IP address of last login")
    )
    
    # Account dates
    email_verified_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name=_("Email Verified At"),
        help_text=_("When the email was verified")
    )
    
    # Override username field to use email for authentication
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username', 'first_name', 'last_name']

    class Meta:
        verbose_name = _("User")
        verbose_name_plural = _("Users")
        ordering = ['-date_joined']
        db_table = 'accounts_user' 
        indexes = [
            models.Index(fields=['email']),
            models.Index(fields=['is_active', 'is_verified']),
            models.Index(fields=['date_joined']),
        ]

    def __str__(self):
        """String representation of the user."""
        return f"{self.get_full_name()} ({self.email})"
    
    def get_full_name(self):
        """Get user's full name."""
        return f"{self.first_name} {self.last_name}".strip() or self.username
    
    def get_short_name(self):
        """Get user's short name."""
        return self.first_name or self.username
    
    def get_user_roles(self):
        """Get list of user's role names."""
        return list(self.roles.filter(is_active=True).values_list('name', flat=True))
    
    def has_role(self, role_name):
        """Check if user has specific role."""
        return self.roles.filter(name=role_name, is_active=True).exists()
    
    def get_all_permissions(self):
        """Get all permissions from user's roles."""
        permissions = set()
        for role in self.roles.filter(is_active=True):
            permissions.update(role.get_permissions_list())
        return list(permissions)
    
    def has_permission(self, permission_codename):
        """Check if user has specific permission through roles."""
        return any(
            role.has_permission(permission_codename) 
            for role in self.roles.filter(is_active=True)
        )
    
    def verify_email(self):
        """Mark user's email as verified."""
        self.is_verified = True
        self.email_verified_at = timezone.now()
        self.save(update_fields=['is_verified', 'email_verified_at'])
    
    def update_last_login_ip(self, ip_address):
        """Update user's last login IP address."""
        self.last_login_ip = ip_address
        self.save(update_fields=['last_login_ip'])

    def clean(self):
        """Validate the model data."""
        super().clean()
        
        # Ensure email is lowercase
        if self.email:
            self.email = self.email.lower()
    
    def save(self, *args, **kwargs):
        """Override save to add custom logic."""
        self.full_clean()
        super().save(*args, **kwargs)
    
    def get_absolute_url(self):
        """Return the absolute URL for the user profile."""
        return reverse('accounts:profile', kwargs={'pk': self.pk})


class Profile(BaseModel):
    """
    Extended user profile model for additional user information.
    
    This model stores additional user data that doesn't belong
    in the core User model, following the principle of separation of concerns.
    """
    
    # One-to-one relationship with User model
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE,
        related_name='profile',
        verbose_name=_("User"),
        help_text=_("Associated user account")
    )

    # Professional information
    job_title = models.CharField(
        _('Job Title'),
        max_length=100,
        blank=True,
        help_text=_('User job title or position')
    )
    
    # Personal information
    bio = models.TextField(
        _('Biography'),
        max_length=500,
        blank=True, 
        help_text=_("User's biography or description")
    )
    
    # Profile image
    avatar = models.ImageField(
        _('Avatar'),
        upload_to='avatars/%Y/%m/',
        blank=True,
        null=True, 
        help_text=_("User's profile picture")
    )
    
    # Birth date
    birth_date = models.DateField(
        null=True,
        blank=True,
        verbose_name=_("Birth Date"),
        help_text=_("User's birth date")
    )
    
    company = models.CharField(
        _('Company'),
        max_length=100,
        blank=True,
        help_text=_('User company or organization')
    )
    
    department = models.CharField(
        _('Department'),
        max_length=100,
        blank=True,
        help_text=_('User department within the company')
    )

    # Website URL
    website = models.URLField(
        blank=True,
        verbose_name=_("Website"),
        help_text=_("User's website URL")
    )
    
    # Address information
    address_line1 = models.CharField(
        _('Address Line 1'),
        max_length=255,
        blank=True,
        help_text=_('Street address')
    )
    
    address_line2 = models.CharField(
        _('Address Line 2'),
        max_length=255,
        blank=True,
        help_text=_('Apartment, suite, etc.')
    )
    
    city = models.CharField(
        _('City'),
        max_length=100,
        blank=True,
        help_text=_('City')
    )
    
    state = models.CharField(
        _('State/Province'),
        max_length=100,
        blank=True,
        help_text=_('State or province')
    )
    
    postal_code = models.CharField(
        _('Postal Code'),
        max_length=20,
        blank=True,
        help_text=_('ZIP or postal code')
    )
    
    country = models.CharField(
        _('Country'),
        max_length=100,
        blank=True,
        help_text=_('Country')
    )

    # Privacy settings
    is_profile_public = models.BooleanField(
        default=True,
        verbose_name=_("Public Profile"),
        help_text=_("Whether the profile is publicly visible")
    )
    
    # Notification preferences
    email_notifications = models.BooleanField(
        default=True,
        verbose_name=_("Email Notifications"),
        help_text=_("Receive email notifications")
    )
    
    sms_notifications = models.BooleanField(
        default=False,
        verbose_name=_("SMS Notifications"),
        help_text=_("Receive SMS notifications")
    )

    class Meta:
        verbose_name = _("User Profile")
        verbose_name_plural = _("User Profiles")
        db_table = 'accounts_profile'
        ordering = ['-created_at']

    def __str__(self):
        """String representation of the user profile."""
        return f"{self.user.get_full_name()}'s Profile"
    
    def get_age(self):
        """Calculate user's age from birth date."""
        if self.birth_date:
            today = timezone.now().date()
            return today.year - self.birth_date.year - (
                (today.month, today.day) < (self.birth_date.month, self.birth_date.day)
            )
        return None
    
    def get_avatar_url(self):
        """Get avatar URL or default avatar."""
        if self.avatar:
            return self.avatar.url
        return '/static/images/default-avatar.png'
    
    def get_absolute_url(self):
        """Return the absolute URL for the user profile."""
        return reverse('accounts:profile', kwargs={'pk': self.user.pk})


class UserSession(TimeStampedModel):
    """Track user sessions for security and analytics.
    
    This model stores information about user login sessions
    for security monitoring and analytics purposes.
    """
    
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='sessions',
        help_text=_('User who owns this session')
    )
    
    session_key = models.CharField(
        _('Session Key'),
        max_length=40,
        unique=True,
        help_text=_('Django session key')
    )
    
    ip_address = models.GenericIPAddressField(
        _('IP Address'),
        help_text=_('IP address of the session')
    )
    
    user_agent = models.TextField(
        _('User Agent'),
        help_text=_('Browser user agent string')
    )
    
    is_active = models.BooleanField(
        _('Is Active'),
        default=True,
        help_text=_('Whether the session is currently active')
    )
    
    expires_at = models.DateTimeField(
        _('Expires At'),
        help_text=_('When the session expires')
    )
    
    class Meta:
        verbose_name = _('User Session')
        verbose_name_plural = _('User Sessions')
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['user', 'is_active']),
            models.Index(fields=['session_key']),
            models.Index(fields=['expires_at']),
        ]
    
    def __str__(self):
        return f"Session for {self.user.get_full_name()} from {self.ip_address}"
    
    def is_expired(self):
        """Check if the session has expired."""
        return timezone.now() > self.expires_at
    
    def deactivate(self):
        """Deactivate the session."""
        self.is_active = False
        self.save(update_fields=['is_active', 'updated_at'])



    # # User preferences
    # timezone_field = models.CharField(
    #     _('Timezone'),
    #     max_length=50,
    #     default='UTC',
    #     help_text=_('User preferred timezone')
    # )
    
    # language = models.CharField(
    #     _('Language'),
    #     max_length=10,
    #     default='en',
    #     choices=[
    #         ('en', _('English')),
    #         ('es', _('Spanish')),
    #         ('fr', _('French')),
    #         ('de', _('German')),
    #     ],
    #     help_text=_('User preferred language')
    # )