"""
Accounts permissions - RBAC permission classes
"""
from rest_framework import permissions


class IsPXAdmin(permissions.BasePermission):
    """
    Permission class to check if user is PX Admin.
    PX Admins have full system access.
    """
    message = "You must be a PX Admin to perform this action."
    
    def has_permission(self, request, view):
        return request.user and request.user.is_authenticated and request.user.is_px_admin()


class IsHospitalAdmin(permissions.BasePermission):
    """
    Permission class to check if user is Hospital Admin.
    Hospital Admins have access to their hospital's data.
    """
    message = "You must be a Hospital Admin to perform this action."
    
    def has_permission(self, request, view):
        return request.user and request.user.is_authenticated and request.user.is_hospital_admin()


class IsDepartmentManager(permissions.BasePermission):
    """
    Permission class to check if user is Department Manager.
    Department Managers have access to their department's data.
    """
    message = "You must be a Department Manager to perform this action."

    def has_permission(self, request, view):
        return request.user and request.user.is_authenticated and request.user.is_department_manager()


class IsDepartmentRespondent(permissions.BasePermission):
    """
    Permission class to check if user is Department Respondent.
    Department Respondents can view and respond to inquiries in their department.
    """
    message = "You must be a Department Respondent to perform this action."

    def has_permission(self, request, view):
        return request.user and request.user.is_authenticated and (
            request.user.is_champion() or request.user.is_department_manager()
        )


class IsExecutive(permissions.BasePermission):
    """
    Permission class to check if user is Executive (C-Suite/Top Management).
    Executives have system-wide read-only access with analytics capabilities.
    """
    message = "You must be an Executive to perform this action."

    def has_permission(self, request, view):
        return request.user and request.user.is_authenticated and request.user.is_executive()


class IsPXAdminOrHospitalAdmin(permissions.BasePermission):
    """
    Permission class for PX Admin or Hospital Admin.
    """
    message = "You must be a PX Admin or Hospital Admin to perform this action."
    
    def has_permission(self, request, view):
        if not (request.user and request.user.is_authenticated):
            return False
        return request.user.is_px_admin() or request.user.is_hospital_admin()


class IsPXAdminOrReadOnly(permissions.BasePermission):
    """
    Permission class that allows PX Admins full access,
    but only read access for others.
    """
    
    def has_permission(self, request, view):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # Read permissions for any authenticated user
        if request.method in permissions.SAFE_METHODS:
            return True
        
        # Write permissions only for PX Admins
        return request.user.is_px_admin()


class IsOwnerOrPXAdmin(permissions.BasePermission):
    """
    Permission class that allows users to access their own data,
    or PX Admins to access any data.
    """
    
    def has_object_permission(self, request, view, obj):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # PX Admins can access anything
        if request.user.is_px_admin():
            return True
        
        # Users can access their own data
        if hasattr(obj, 'user'):
            return obj.user == request.user
        
        return obj == request.user


class HasRolePermission(permissions.BasePermission):
    """
    Permission class that checks if user has specific role.
    Usage: Set required_roles on the view.
    """
    
    def has_permission(self, request, view):
        if not (request.user and request.user.is_authenticated):
            return False
        
        required_roles = getattr(view, 'required_roles', [])
        if not required_roles:
            return True
        
        user_roles = request.user.get_role_names()
        return any(role in user_roles for role in required_roles)


class CanAccessHospitalData(permissions.BasePermission):
    """
    Permission class that checks if user can access hospital data.
    - PX Admins can access all hospitals
    - Hospital Admins can access their own hospital
    - Department Managers can access their hospital
    """
    
    def has_object_permission(self, request, view, obj):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # PX Admins can access all
        if request.user.is_px_admin():
            return True
        
        # Get hospital from object
        hospital = None
        if hasattr(obj, 'hospital'):
            hospital = obj.hospital
        elif obj.__class__.__name__ == 'Hospital':
            hospital = obj
        
        if not hospital:
            return False
        
        # Check if user belongs to this hospital
        return request.user.hospital == hospital


class CanAccessDepartmentData(permissions.BasePermission):
    """
    Permission class that checks if user can access department data.
    - PX Admins can access all departments
    - Hospital Admins can access departments in their hospital
    - Department Managers can access their own department
    """
    
    def has_object_permission(self, request, view, obj):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # PX Admins can access all
        if request.user.is_px_admin():
            return True
        
        # Get department from object
        department = None
        if hasattr(obj, 'department'):
            department = obj.department
        elif obj.__class__.__name__ == 'Department':
            department = obj
        
        if not department:
            return False
        
        # Hospital Admins can access departments in their hospital
        if request.user.is_hospital_admin() and request.user.hospital == department.hospital:
            return True
        
        # Department Managers can access their own department
        if request.user.is_department_manager() and request.user.department == department:
            return True
        
        return False


class IsSourceUser(permissions.BasePermission):
    """
    Permission class to check if user is a PX Source User.
    Source Users can only access data from their assigned source.
    """
    message = "You must be a Source User to perform this action."
    
    def has_permission(self, request, view):
        return (
            request.user and 
            request.user.is_authenticated and 
            request.user.is_source_user()
        )


class IsSourceUserOrAdmin(permissions.BasePermission):
    """
    Permission class for Source Users or Admins.
    Allows access to:
    - PX Admins
    - Hospital Admins  
    - Department Managers
    - Active Source Users
    """
    message = "You must be a Source User or Admin to perform this action."
    
    def has_permission(self, request, view):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # Admins have access
        if (request.user.is_px_admin() or 
            request.user.is_hospital_admin() or 
            request.user.is_department_manager()):
            return True
        
        # Source Users have access
        return request.user.is_source_user()


class IsSourceUserOwnData(permissions.BasePermission):
    """
    Object-level permission to ensure source users can only access their own data.
    """
    message = "You can only access data you created."
    
    def has_object_permission(self, request, view, obj):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # Admins can access everything
        if (request.user.is_px_admin() or 
            request.user.is_hospital_admin() or 
            request.user.is_department_manager()):
            return True
        
        # Source Users can only access their own created data
        if request.user.is_source_user():
            return getattr(obj, 'created_by', None) == request.user
        
        return False


# ==================== Onboarding Permissions ====================

class IsProvisionalUser(permissions.BasePermission):
    """
    Permission class to check if user is provisional (in onboarding).
    """
    message = "You must be a provisional user to access this resource."
    
    def has_permission(self, request, view):
        return (
            request.user and 
            request.user.is_authenticated and 
            request.user.is_provisional and
            not request.user.acknowledgement_completed
        )


class CanViewOnboarding(permissions.BasePermission):
    """
    Permission class for viewing onboarding content.
    - Provisional users can view their own onboarding
    - PX Admins can view all onboarding data
    """
    message = "You do not have permission to view onboarding data."
    
    def has_permission(self, request, view):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # Provisional users can view their own
        if request.user.is_provisional:
            return True
        
        # PX Admins can view all
        if request.user.is_px_admin():
            return True
        
        return False


class CanManageOnboarding(permissions.BasePermission):
    """
    Permission class for managing onboarding.
    - PX Admins have full access
    - Hospital Admins can manage onboarding for their hospital
    """
    message = "You must be a PX Admin or Hospital Admin to manage onboarding."
    
    def has_permission(self, request, view):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # PX Admins have full access
        if request.user.is_px_admin():
            return True
        
        # Hospital Admins can manage their hospital
        if request.user.is_hospital_admin():
            return True
        
        return False


class IsOnboardingOwnerOrAdmin(permissions.BasePermission):
    """
    Permission class for onboarding object access.
    - Users can access their own onboarding data
    - PX Admins can access all
    """
    
    def has_object_permission(self, request, view, obj):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # PX Admins can access all
        if request.user.is_px_admin():
            return True
        
        # Users can access their own data
        if hasattr(obj, 'user'):
            return obj.user == request.user
        
        return obj == request.user


class CanManageAcknowledgementContent(permissions.BasePermission):
    """
    Permission class for managing acknowledgement content and checklist items.
    Only PX Admins can manage these.
    """
    message = "Only PX Admins can manage acknowledgement content."
    
    def has_permission(self, request, view):
        if not (request.user and request.user.is_authenticated):
            return False
        
        # PX Admins can manage content
        if request.user.is_px_admin():
            return True
        
        # Read-only for others
        if request.method in permissions.SAFE_METHODS:
            return True
        
        return False
