"""
Multi-tenancy mixins and utilities for Sales Shark.
Provides schema-based tenant isolation and routing functionality.
"""

from django.shortcuts import get_object_or_404
from django.core.exceptions import PermissionDenied
from .models import Tenant
from .router import set_tenant, get_current_tenant, get_tenant_schema_name


def get_tenant_or_404(request):
    """
    Get the current tenant from request context and set schema routing.
    Returns the tenant object or raises 404 if not found.
    
    This function now also handles schema routing for database isolation.
    """
    if hasattr(request, 'tenant') and request.tenant:
        # Ensure schema is set for this tenant
        set_tenant(request.tenant)
        return request.tenant
    
    # Extract tenant_code from domain or session
    if hasattr(request, 'session') and 'tenant_code' in request.session:
        tenant_code = request.session['tenant_code']
    elif hasattr(request, 'GET') and 'tenant' in request.GET:
        tenant_code = request.GET['tenant']
    else:
        # Default fallback - get first tenant for development
        tenant = Tenant.objects.first()
        if not tenant:
            raise PermissionDenied("No tenant available")
        # Set schema routing for this tenant
        set_tenant(tenant)
        # Cache on request object
        if hasattr(request, '__dict__'):
            request.tenant = tenant
        return tenant
    
    # Get tenant by code - using public schema since tenant data is in public
    set_tenant(None)  # Ensure we're in public schema for tenant lookup
    tenant = get_object_or_404(Tenant, tenant_code=tenant_code)
    
    # Set schema routing for this tenant
    set_tenant(tenant)
    
    # Cache on request object
    if hasattr(request, '__dict__'):
        request.tenant = tenant
    
    return tenant


def filter_by_tenant(queryset, tenant):
    """
    DEPRECATED: Schema separation makes tenant filtering unnecessary.
    
    With schema-based isolation, queries are automatically scoped to 
    the current tenant's schema. This function is kept for compatibility
    but will return the queryset unchanged.
    
    Usage: 
        # No longer needed - queries are automatically tenant-scoped
        customers = Customer.objects.all()  # Only returns current tenant's data
    """
    # With schema separation, no filtering needed - return queryset as-is
    return queryset


def tenant_scoped_get_or_404(model, tenant, **kwargs):
    """
    DEPRECATED: Schema-based isolation makes tenant scoping automatic.
    
    With schema separation, get_object_or_404 automatically searches
    within the current tenant's schema.
    """
    return get_object_or_404(model, **kwargs)


class TenantScopedMixin:
    """
    Mixin for Class-Based Views with schema-based tenant isolation.
    
    Automatically sets tenant context and schema routing.
    No queryset filtering needed - schema isolation handles it.
    
    Usage in CBVs:
        class CustomerListView(TenantScopedMixin, ListView):
            model = Customer
    """
    
    def dispatch(self, request, *args, **kwargs):
        """Set tenant context before processing the request."""
        self.tenant = get_tenant_or_404(request)
        return super().dispatch(request, *args, **kwargs)
    
    def get_queryset(self):
        """Return standard queryset - schema isolation handles tenant scoping."""
        return super().get_queryset()
    
    def get_object(self, queryset=None):
        """Return standard object lookup - schema isolation handles tenant scoping."""
        return super().get_object(queryset=queryset)
    
    def form_valid(self, form):
        """Process valid form - no tenant assignment needed with schema isolation."""
        return super().form_valid(form)


class TenantObjectMixin:
    """
    DEPRECATED: Schema-based isolation makes object-level checks unnecessary.
    
    With schema separation, objects are automatically scoped to the current
    tenant's schema, so no additional verification is needed.
    """
    
    def get_object(self, queryset=None):
        """Return standard object lookup - schema isolation handles tenant scoping."""
        return super().get_object(queryset)