from django.db import models
from coresite.mixin import AbstractTimeStampModel
from django.contrib.auth.models import (
    BaseUserManager,
    AbstractBaseUser,
)
from apps.permissions.models import Role

class UserManager(BaseUserManager):
    def create_user(self, email, username=None, password=None, user_type='user', companies=None):
        """
        Creates and saves a User with the given email, username, password and companies.
        """
        if not email:
            raise ValueError('Users must have an email address')

        # Auto-generate username from email if not provided
        if not username:
            username = email.split('@')[0]  # Get part before @

            # Ensure username is unique by adding numbers if needed
            base_username = username
            counter = 1
            while User.objects.filter(username=username).exists():
                username = f"{base_username}{counter}"
                counter += 1

        user = self.model(
            email=self.normalize_email(email),
            username=username,
            user_type=user_type,
        )
        user.is_staff = True
        user.is_active = True
        user.set_password(password)
        user.must_change_password = True
        user.save()
        
        # Add companies if provided
        if companies:
            user.companies.set(companies)
            # Set company as active if user doesn't have one
            if not user.active_company:
                for company in companies:
                    company_has_role = Role.objects.filter(
                        company=company,
                    ).exists()
                    if company_has_role:
                        user.active_company = company
                        user.save()
                        return user

                if companies:
                    user.active_company = companies[0]
                    user.save()
        
        return user

    def create_superuser(self, email, username=None, password=None, user_type='super_admin'):
        """
        Creates and saves a superuser with the given email, date of
        birth and password.
        """
        user = self.create_user(
            email,
            password=password,
            username=username,
            user_type=user_type,
        )
        user.is_admin = True
        user.is_staff = True
        user.is_active = True
        user.is_superuser = True
        user.must_change_password=False
        user.user_type = 'super_admin'
        user.save()
        return user


USER_TYPE_CHOICES = (
    ('user', 'User'),
    ('admin', 'Admin'),
    ('super_admin', 'Super Admin'),
)


class User(AbstractBaseUser, AbstractTimeStampModel):
    """
    Our custom user model that extends Django's AbstractBaseUser."""
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    user_type = models.CharField(
        max_length=255, default='user', choices=USER_TYPE_CHOICES)
    username = models.CharField(max_length=255, unique=True, blank=True, null=True)
    is_active = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)
    is_available = models.BooleanField(
        default=True,
        help_text="Whether the user is currently available for work/assignments"
    )

    must_change_password = models.BooleanField(
        default=True,
        help_text="User must change password after first login"
    )
    # Multi-tenant: Link user to multiple companies
    companies = models.ManyToManyField(
        'companies.Company',
        related_name='users',
        blank=True,
        help_text="Companies this user belongs to"
    )

    # Currently active company for the session
    active_company = models.ForeignKey(
        'companies.Company',
        on_delete=models.SET_NULL,
        related_name='active_users',
        null=True,
        blank=True,
        help_text="Currently active company for this user"
    )

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['password']

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True
    
    # Company-related methods
    def belongs_to_company(self, company):
        """Check if user belongs to a specific company"""
        return self.companies.filter(id=company.id).exists()
    
    def get_active_company(self):
        """Get the active company for the user"""
        return self.active_company
    
    def get_active_company_name(self):
        """Get the name of user's active company"""
        return self.active_company.name if self.active_company else None
    
    def is_company_admin(self, company=None):
        """Check if user is admin of their company"""
        target_company = company or self.active_company
        return self.user_type in ['admin', 'super_admin'] and target_company is not None
    
    def get_role_in_company(self, company=None):
        """Get user's role in a specific company"""
        from apps.permissions.models import UserCompanyRole
        target_company = company or self.active_company
        if not target_company:
            return None
            
        user_role = UserCompanyRole.objects.filter(
            user=self,
            company=target_company,
            is_active=True
        ).first()
        return user_role.role if user_role else None
    
    def has_company_permission(self, permission_codename, company=None):
        """Check if user has specific permission in their company context"""
        if self.is_superuser:
            return True

        target_company = company or self.active_company
        if not target_company:
            return False
            
        role = self.get_role_in_company(target_company)
        if role and role.company == target_company:
            return role.permissions.filter(
                codename=permission_codename, 
                is_active=True
            ).exists()
            
        return False

    def get_all_permissions(self, company=None):
        """Get all permissions for the user in a specific company context"""
        if self.is_superuser:
            from apps.permissions.models import Permission
            return Permission.objects.filter(is_active=True)
            
        target_company = company or self.active_company
        if not target_company:
            return []
            
        role = self.get_role_in_company(target_company)
        if role and role.company == target_company:
            return role.permissions.filter(is_active=True)
            
        return []
    
    def switch_company(self, company):
        """Switch user's active company"""
        if self.belongs_to_company(company):
            self.active_company = company
            self.save()
            return True
        return False
    
    def set_default_company(self, company):
        """Set user's default company (first in list)"""
        if self.belongs_to_company(company):
            # Move this company to the front of the companies list
            companies_list = list(self.companies.all())
            if company in companies_list:
                companies_list.remove(company)
            companies_list.insert(0, company)
            self.companies.set(companies_list)
            self.active_company = company
            self.save()
            return True
        return False
    
    def clean(self):
        """Validate that active_company is one of user's companies"""
        super().clean()
        if self.active_company and not self.belongs_to_company(self.active_company):
            from django.core.exceptions import ValidationError
            raise ValidationError({
                'active_company': f'Active company "{self.active_company.name}" is not in user\'s companies list'
            })
    
    def save(self, *args, **kwargs):
        """Override save to validate active_company relationship"""
        self.clean()
        super().save(*args, **kwargs)
