"""
User Models with Multi-Role System
Supports: Admin, Staff (various roles), and Customers
"""
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models
from django.utils.translation import gettext_lazy as _
import random
import string
from django.utils import timezone


class UserManager(BaseUserManager):
    """Custom user manager for email-based authentication"""
    
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError(_('The Email field must be set'))
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user
    
    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)
        extra_fields.setdefault('role', 'ADMIN')
        
        if extra_fields.get('is_staff') is not True:
            raise ValueError(_('Superuser must have is_staff=True.'))
        if extra_fields.get('is_superuser') is not True:
            raise ValueError(_('Superuser must have is_superuser=True.'))
        
        return self.create_user(email, password, **extra_fields)


class User(AbstractUser):
    """
    Custom User Model with Role-Based Access Control
    """
    
    class Role(models.TextChoices):
        ADMIN = 'ADMIN', _('Administrator')
        STAFF_ADMIN = 'STAFF_ADMIN', _('Staff Admin')
        ACCOUNTANT = 'ACCOUNTANT', _('Accountant')
        INVENTORY_MANAGER = 'INVENTORY', _('Inventory Manager')
        SALES_MANAGER = 'SALES', _('Sales Manager')
        CUSTOMER_SUPPORT = 'SUPPORT', _('Customer Support')
        CONTENT_MANAGER = 'CONTENT', _('Content Manager')
        MARKETING = 'MARKETING', _('Marketing Staff')
        VENDOR = 'VENDOR', _('Vendor')
        CUSTOMER = 'CUSTOMER', _('Customer')
    
    username = None
    email = models.EmailField(_('email address'), unique=True)
    unique_code = models.CharField(max_length=12, unique=True, blank=True, null=True)
    phone = models.CharField(max_length=15, blank=True, null=True)
    role = models.CharField(
        max_length=20,
        choices=Role.choices,
        default=Role.CUSTOMER
    )
    
    # Profile Information
    profile_picture = models.ImageField(
        upload_to='profile_pictures/',
        blank=True,
        null=True
    )
    email_verified = models.BooleanField(default=False)
    phone_verified = models.BooleanField(default=False)
    date_of_birth = models.DateField(blank=True, null=True)
    address = models.TextField(blank=True)
    city = models.CharField(max_length=100, blank=True)
    state = models.CharField(max_length=100, blank=True)
    country = models.CharField(max_length=100, default='India')
    pincode = models.CharField(max_length=10, blank=True)
    
    # Verification & Status
    is_verified = models.BooleanField(default=False)
    verification_token = models.CharField(max_length=100, blank=True)
    
    # KYC
    aadhaar_no = models.CharField(max_length=12, blank=True)
    gst_no = models.CharField(max_length=15, blank=True)
    consent_form = models.FileField(upload_to='kyc/consent_forms/', blank=True, null=True)
    kyc_photo = models.ImageField(upload_to='kyc/photos/', blank=True, null=True)
    kyc_address_proof = models.ImageField(upload_to='kyc/address_proofs/', blank=True, null=True)
    kyc_submitted = models.BooleanField(default=False)
    kyc_approved = models.BooleanField(default=False)
    
    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    last_login = models.DateTimeField(blank=True, null=True)
    
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []
    
    objects = UserManager()
    
    class Meta:
        ordering = ['-created_at']
        verbose_name = _('User')
        verbose_name_plural = _('Users')
        indexes = [
            models.Index(fields=['email']),
            models.Index(fields=['role']),
        ]
    
    def __str__(self):
        return f"{self.email} ({self.get_role_display()})"
    
    def save(self, *args, **kwargs):
        if not self.unique_code:
            for _ in range(100):
                code = ''.join(random.choices(string.ascii_uppercase, k=4)) + ''.join(random.choices(string.digits, k=8))
                if not type(self).objects.filter(unique_code=code).exists():
                    self.unique_code = code
                    break
        super().save(*args, **kwargs)
    
    @property
    def full_name(self):
        return f"{self.first_name} {self.last_name}".strip() or self.email
    
    @property
    def is_admin(self):
        return self.role == self.Role.ADMIN or self.is_superuser
    
    @property
    def is_staff_member(self):
        return self.role in [
            self.Role.ADMIN,
            self.Role.STAFF_ADMIN,
            self.Role.ACCOUNTANT,
            self.Role.INVENTORY_MANAGER,
            self.Role.SALES_MANAGER,
            self.Role.CUSTOMER_SUPPORT,
            self.Role.CONTENT_MANAGER,
            self.Role.MARKETING
        ]
    
    def has_permission(self, permission):
        """Check if user has specific permission based on role"""
        permissions_map = {
            self.Role.ADMIN: ['all'],
            self.Role.STAFF_ADMIN: ['all'],
            self.Role.ACCOUNTANT: ['manage_finance', 'view_analytics', 'view_orders', 'manage_orders'],
            self.Role.INVENTORY_MANAGER: ['manage_inventory', 'view_products', 'manage_products'],
            self.Role.SALES_MANAGER: ['view_orders', 'manage_orders', 'view_analytics'],
            self.Role.CUSTOMER_SUPPORT: ['view_orders', 'manage_customer_queries'],
            self.Role.CONTENT_MANAGER: ['manage_products', 'manage_categories'],
            self.Role.MARKETING: ['view_analytics', 'manage_promotions'],
            self.Role.CUSTOMER: ['place_orders', 'view_own_orders'],
        }
        
        user_perms = permissions_map.get(self.role, [])
        return 'all' in user_perms or permission in user_perms


class VerificationCode(models.Model):
    """
    Six-digit verification codes for email/phone
    """
    class Channel(models.TextChoices):
        EMAIL = 'email', _('Email')
        PHONE = 'phone', _('Phone')
    user = models.ForeignKey('accounts.User', on_delete=models.CASCADE, related_name='verification_codes')
    channel = models.CharField(max_length=10, choices=Channel.choices)
    code = models.CharField(max_length=6)
    contact_value = models.CharField(max_length=255, blank=True)
    expires_at = models.DateTimeField()
    attempts = models.IntegerField(default=0)
    max_attempts = models.IntegerField(default=5)
    is_used = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    class Meta:
        indexes = [
            models.Index(fields=['user', 'channel', 'is_used']),
            models.Index(fields=['expires_at']),
        ]
        ordering = ['-created_at']
    def __str__(self):
        return f"{self.user_id}-{self.channel}-{self.code}"
    def is_expired(self):
        return timezone.now() >= self.expires_at

class Address(models.Model):
    """Customer shipping addresses"""
    
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='addresses'
    )
    full_name = models.CharField(max_length=200)
    phone = models.CharField(max_length=15)
    address_line1 = models.CharField(max_length=255)
    address_line2 = models.CharField(max_length=255, blank=True)
    city = models.CharField(max_length=100)
    state = models.CharField(max_length=100)
    country = models.CharField(max_length=100, default='India')
    pincode = models.CharField(max_length=10)
    is_default = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        verbose_name_plural = 'Addresses'
        ordering = ['-is_default', '-created_at']
    
    def __str__(self):
        return f"{self.full_name} - {self.city}, {self.state}"
    
    def save(self, *args, **kwargs):
        # Make sure only one default address per user
        if self.is_default:
            Address.objects.filter(
                user=self.user,
                is_default=True
            ).update(is_default=False)
        super().save(*args, **kwargs)


class Wishlist(models.Model):
    """Customer wishlist"""
    
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='wishlist_items'
    )
    product = models.ForeignKey(
        'products.Product',
        on_delete=models.CASCADE
    )
    added_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        unique_together = ('user', 'product')
        ordering = ['-added_at']
    
    def __str__(self):
        return f"{self.user.email} - {self.product.name}"
