"""
Centralized filtering utilities for branch and portfolio access control
"""
from django.db.models import Q


def apply_branch_and_portfolio_filters(queryset, user, selected_branch_id=None, model_type='loan'):
    """
    Apply branch and portfolio filtering to any queryset based on user role and permissions.
    
    Args:
        queryset: Django queryset to filter
        user: Current user making the request
        selected_branch_id: Optional branch ID from session
        model_type: Type of model being filtered ('loan', 'client', 'repayment', 'application', 'document', 'notification')
    
    Returns:
        Filtered queryset
    """
    # Superusers see everything
    if user.is_superuser:
        if selected_branch_id:
            return apply_branch_filter(queryset, selected_branch_id, model_type)
        return queryset
    
    # Admin users see everything in their selected branch or all branches
    if user.role == 'admin':
        if selected_branch_id:
            return apply_branch_filter(queryset, selected_branch_id, model_type)
        return queryset
    
    # Loan officers and team leaders see only their portfolio
    if user.role in ['loan_officer', 'team_leader']:
        queryset = apply_portfolio_filter(queryset, user, model_type)
        # Also apply branch filter if selected
        if selected_branch_id:
            queryset = apply_branch_filter(queryset, selected_branch_id, model_type)
        return queryset
    
    # Secretaries and auditors see only their branch
    if user.role in ['secretary', 'auditor']:
        if hasattr(user, 'branch') and user.branch:
            queryset = apply_branch_filter(queryset, user.branch.id, model_type)
        # Also apply selected branch if different
        elif selected_branch_id:
            queryset = apply_branch_filter(queryset, selected_branch_id, model_type)
        return queryset
    
    # Default: apply branch filter if available
    if selected_branch_id:
        return apply_branch_filter(queryset, selected_branch_id, model_type)
    
    return queryset


def apply_branch_filter(queryset, branch_id, model_type='loan'):
    """
    Apply branch filtering based on model type.
    
    Args:
        queryset: Django queryset to filter
        branch_id: Branch ID to filter by
        model_type: Type of model being filtered
    
    Returns:
        Filtered queryset
    """
    if not branch_id:
        return queryset
    
    filter_map = {
        'loan': {'borrower__branch_id': branch_id},
        'client': {'branch_id': branch_id},
        'repayment': {'loan__borrower__branch_id': branch_id},
        'application': {'borrower__branch_id': branch_id},
        'document': {'client__branch_id': branch_id},
        'notification': {'user__branch_id': branch_id},
        'mpesa_transaction': {'loan__borrower__branch_id': branch_id},
        'rollover': {'original_loan__borrower__branch_id': branch_id},
        'audit_log': Q(user__branch_id=branch_id) | Q(user__isnull=True),
    }
    
    filter_condition = filter_map.get(model_type, {})
    
    if isinstance(filter_condition, Q):
        return queryset.filter(filter_condition)
    
    return queryset.filter(**filter_condition)


def apply_portfolio_filter(queryset, user, model_type='loan'):
    """
    Apply portfolio filtering - staff can only see their assigned clients.
    
    Args:
        queryset: Django queryset to filter
        user: Current user (portfolio manager)
        model_type: Type of model being filtered
    
    Returns:
        Filtered queryset
    """
    filter_map = {
        'loan': {'borrower__portfolio_manager': user},
        'client': {'portfolio_manager': user},
        'repayment': {'loan__borrower__portfolio_manager': user},
        'application': {'borrower__portfolio_manager': user},
        'document': {'client__portfolio_manager': user},
        'notification': {'user__portfolio_manager': user},
        'mpesa_transaction': {'loan__borrower__portfolio_manager': user},
        'rollover': {'original_loan__borrower__portfolio_manager': user},
    }
    
    filter_condition = filter_map.get(model_type, {})
    return queryset.filter(**filter_condition)


def get_filtered_clients(user, selected_branch_id=None):
    """Get clients filtered by branch and portfolio."""
    from users.models import CustomUser
    
    queryset = CustomUser.objects.filter(role='borrower')
    return apply_branch_and_portfolio_filters(queryset, user, selected_branch_id, 'client')


def get_filtered_loans(user, selected_branch_id=None):
    """Get loans filtered by branch and portfolio."""
    from loans.models import Loan
    
    queryset = Loan.objects.filter(is_deleted=False)
    return apply_branch_and_portfolio_filters(queryset, user, selected_branch_id, 'loan')


def get_filtered_applications(user, selected_branch_id=None):
    """Get loan applications filtered by branch and portfolio."""
    from loans.models import LoanApplication
    
    queryset = LoanApplication.objects.all()
    return apply_branch_and_portfolio_filters(queryset, user, selected_branch_id, 'application')


def get_filtered_repayments(user, selected_branch_id=None):
    """Get repayments filtered by branch and portfolio."""
    from loans.models import Repayment
    
    queryset = Repayment.objects.all()
    return apply_branch_and_portfolio_filters(queryset, user, selected_branch_id, 'repayment')


def get_filtered_documents(user, selected_branch_id=None):
    """Get documents filtered by branch and portfolio."""
    from utils.models import Document
    
    queryset = Document.objects.all()
    return apply_branch_and_portfolio_filters(queryset, user, selected_branch_id, 'document')


def get_filtered_notifications(user, selected_branch_id=None):
    """Get notifications filtered by branch and portfolio."""
    from utils.models import Notification
    
    queryset = Notification.objects.all()
    return apply_branch_and_portfolio_filters(queryset, user, selected_branch_id, 'notification')


def get_user_context(user):
    """
    Get user context for filtering including role, branch, and portfolio info.
    
    Returns:
        dict with user filtering context
    """
    context = {
        'user': user,
        'role': user.role,
        'is_superuser': user.is_superuser,
        'is_admin': user.role == 'admin' or user.is_superuser,
        'is_portfolio_manager': user.role in ['loan_officer', 'team_leader'],
        'is_branch_staff': user.role in ['secretary', 'auditor'],
        'branch_id': user.branch.id if hasattr(user, 'branch') and user.branch else None,
        'branch_name': user.branch.name if hasattr(user, 'branch') and user.branch else None,
    }
    
    return context
