# org_authz/views/mixins.py

from rest_framework import viewsets, permissions
from django.db.models import ForeignKey
from org_authz.models import UserRole, Organization


class OrgAuthzViewSet(viewsets.ModelViewSet):
    """
    Generic organization-aware ViewSet.
    Dynamically detects any direct or nested relationship to an Organization (or subclass)
    and filters querysets to only include data belonging to organizations
    that the current user has access to.
    """

    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        queryset = super().get_queryset()
        user = self.request.user

        # Get organizations this user is allowed to access
        org_ids = list(
            UserRole.objects.filter(user=user)
            .values_list("organization_id", flat=True)
        )

        if not org_ids:
            return queryset.none()

        # Find a field path (direct or nested) to the Organization model
        org_path = self._find_organization_path(queryset.model)

        if org_path:
            filter_kwargs = {f"{org_path}__in": org_ids}
            return queryset.filter(**filter_kwargs).distinct()

        # If no organization relation detected, return the full queryset
        return queryset

    def _find_organization_path(self, model, prefix=""):
        """
        Recursively search for a ForeignKey path to an Organization or subclass.
        Returns a string like 'organization', 'pharmacy__organization', etc.
        """

        for field in model._meta.get_fields():
            # Skip reverse and M2M relations
            if not isinstance(field, ForeignKey):
                continue

            related_model = field.related_model
            path = f"{prefix}{field.name}"

            # Case 1: direct organization reference
            if issubclass(related_model, Organization):
                return path

            # Case 2: nested model — search deeper
            nested_path = self._find_organization_path(related_model, prefix=f"{path}__")
            if nested_path:
                return nested_path

        # No organization relation found
        return None
