from rest_framework import permissions


class TransferPermission(permissions.BasePermission):
    """
    Custom permission for transfer operations
    """
    
    def has_permission(self, request, view):
        """Check if user has general permission to access transfers"""
        if not request.user.is_authenticated:
            return False
        
        # For list/create actions, check business membership
        business_id = request.query_params.get('business_id') or request.data.get('business_id')
        
        if not business_id:
            # If no business_id provided, allow - will be validated in view
            return True
        
        # Check if user has active membership in the business
        membership = request.user.business_memberships.filter(
            business_id=business_id,
            status='ACTIVE'
        ).first()
        
        if not membership:
            return False
        
        # Check role-based permissions for different actions
        action = view.action
        role_name = membership.role.name
        
        # View permissions
        if action in ['list', 'retrieve']:
            return role_name in ['OWNER', 'ADMIN', 'MANAGER', 'INVENTORY_MANAGER', 'VIEWER']
        
        # Create permissions
        if action == 'create':
            return role_name in ['OWNER', 'ADMIN', 'MANAGER', 'INVENTORY_MANAGER']
        
        # Update/delete permissions
        if action in ['update', 'partial_update']:
            return role_name in ['OWNER', 'ADMIN', 'MANAGER']
        
        if action == 'destroy':
            return role_name in ['OWNER', 'ADMIN']
        
        # Approve/reject permissions
        if action in ['approve', 'reject']:
            return role_name in ['OWNER', 'ADMIN', 'MANAGER']
        
        # Ship/receive permissions
        if action in ['ship', 'receive', 'delivered']:
            return role_name in ['OWNER', 'ADMIN', 'MANAGER', 'INVENTORY_MANAGER']
        
        # Comment permissions
        if action in ['add_comment', 'comments']:
            return role_name in ['OWNER', 'ADMIN', 'MANAGER', 'INVENTORY_MANAGER']
        
        # Cancel permission
        if action == 'cancel':
            return role_name in ['OWNER', 'ADMIN', 'MANAGER']
        
        # Stats and reports
        if action in ['stats', 'pending', 'in_transit', 'location_summary']:
            return role_name in ['OWNER', 'ADMIN', 'MANAGER', 'ACCOUNTANT']
        
        # Default: allow for other actions (will be checked at object level)
        return True
    
    def has_object_permission(self, request, view, obj):
        """Check if user has permission to access specific transfer"""
        if not request.user.is_authenticated:
            return False
        
        # Check if user has active membership in the transfer's business
        membership = request.user.business_memberships.filter(
            business=obj.business,
            status='ACTIVE'
        ).first()
        
        if not membership:
            return False
        
        role_name = membership.role.name
        
        # Owners and admins can access all transfers
        if role_name in ['OWNER', 'ADMIN']:
            return True
        
        # Check location-based access for other roles
        if membership.can_access_all_locations:
            return True
        
        # Check if user has access to source or destination location
        accessible_locations = membership.accessible_locations.values_list('id', flat=True)
        has_location_access = (
            obj.source_location_id in accessible_locations or
            obj.destination_location_id in accessible_locations
        )
        
        if not has_location_access:
            return False
        
        # Check action-specific permissions
        action = view.action
        
        # View permissions
        if action in ['retrieve', 'events', 'comments']:
            return role_name in ['OWNER', 'ADMIN', 'MANAGER', 'INVENTORY_MANAGER', 'VIEWER']
        
        # Update permissions (only PENDING transfers)
        if action in ['update', 'partial_update']:
            if obj.status != 'PENDING':
                return False
            return role_name in ['OWNER', 'ADMIN', 'MANAGER']
        
        # Delete permissions (only PENDING transfers)
        if action == 'destroy':
            if obj.status != 'PENDING':
                return False
            return role_name in ['OWNER', 'ADMIN']
        
        # Approve/reject permissions
        if action in ['approve', 'reject']:
            return role_name in ['OWNER', 'ADMIN', 'MANAGER']
        
        # Ship permission (must have access to source location)
        if action == 'ship':
            if obj.source_location_id not in accessible_locations:
                return False
            return role_name in ['OWNER', 'ADMIN', 'MANAGER', 'INVENTORY_MANAGER']
        
        # Receive permission (must have access to destination location)
        if action in ['receive', 'delivered']:
            if obj.destination_location_id not in accessible_locations:
                return False
            return role_name in ['OWNER', 'ADMIN', 'MANAGER', 'INVENTORY_MANAGER']
        
        # Comment permissions
        if action == 'add_comment':
            return role_name in ['OWNER', 'ADMIN', 'MANAGER', 'INVENTORY_MANAGER']
        
        # Cancel permission
        if action == 'cancel':
            return role_name in ['OWNER', 'ADMIN', 'MANAGER']
        
        # Default: deny
        return False


def can_access_transfer(user, transfer):
    """
    Helper function to check if user can access a specific transfer
    Used in custom views or business logic
    """
    membership = user.business_memberships.filter(
        business=transfer.business,
        status='ACTIVE'
    ).first()
    
    if not membership:
        return False
    
    # Owners and admins can access all transfers
    if membership.role.name in ['OWNER', 'ADMIN']:
        return True
    
    # Check location access
    if membership.can_access_all_locations:
        return True
    
    # Check if user has access to source or destination location
    accessible_locations = membership.accessible_locations.values_list('id', flat=True)
    return (
        transfer.source_location_id in accessible_locations or
        transfer.destination_location_id in accessible_locations
    )