
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from customers.models import Customer
from hr.models import Employee

User = get_user_model()


class SuperuserAuthBackend(ModelBackend):
    """
    Authentication backend specifically for superusers and staff
    """
    
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None or password is None:
            return None
        
        try:
            user = User.objects.get(username=username)
            
            # Allow superusers to authenticate
            if user.is_superuser and user.check_password(password) and user.is_active:
                return user
                
            # Also allow staff users without employee profiles
            if (user.is_staff and not hasattr(user, 'employee_profile') and 
                user.check_password(password) and user.is_active):
                return user
                
        except User.DoesNotExist:
            return None
        
        return None


class EmployeeAuthBackend(ModelBackend):
    """
    Authentication backend specifically for employees
    """
    
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None or password is None:
            return None
        
        user = None
        
        # Try to find user by employee ID
        try:
            employee = Employee.objects.get(employee_id=username, employment_status='active')
            if employee.user and employee.user.is_active:
                user = employee.user
        except Employee.DoesNotExist:
            return None
        
        # Check password if user found
        if user and user.check_password(password):
            return user
        
        return None


class CustomerAuthBackend(ModelBackend):
    """
    Authentication backend specifically for customers
    """
    
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None or password is None:
            return None
        
        user = None
        
        # Try to find user by customer ID
        try:
            customer = Customer.objects.get(customer_id=username, is_active=True)
            if customer.user and customer.user.is_active:
                user = customer.user
        except Customer.DoesNotExist:
            return None
        
        # Check password if user found
        if user and user.check_password(password):
            return user
        
        return None


class CustomerEmployeeAuthBackend(ModelBackend):
    """
    Custom authentication backend that allows login with:
    - Employee ID (for employees)
    - Customer ID (for customers)
    - Regular username (for admin users)
    """
    
    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None or password is None:
            return None
        
        user = None
        
        # First, try to find user by employee ID
        try:
            employee = Employee.objects.get(employee_id=username, employment_status='active')
            if employee.user:
                user = employee.user
        except Employee.DoesNotExist:
            pass
        
        # If not found as employee, try customer ID
        if not user:
            try:
                customer = Customer.objects.get(customer_id=username)
                if customer.user:
                    user = customer.user
            except Customer.DoesNotExist:
                pass
        
        # If still not found, try regular username lookup
        if not user:
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                pass
        
        # Check password if user found
        if user and user.check_password(password):
            return user
        
        return None
    
    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None
