"""
Tenant-aware middleware for multi-tenancy
"""

from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin


class TenantMiddleware(MiddlewareMixin):
    """
    Middleware that sets the current hospital context from the authenticated user.

    This middleware ensures that:
    - authenticated users have their tenant_hospital set from their profile
    - PX admins can switch between hospitals via session
    - PX admins without a selected hospital are redirected to select-hospital
    - Source Users have their source context available
    - All requests have tenant context available
    """

    EXEMPT_PATHS = [
        "/core/select-hospital/",
        "/accounts/logout/",
        "/accounts/password_reset/",
        "/accounts/password_reset/done/",
        "/accounts/reset/",
        "/api/",
        "/health/",
        "/admin/",
        "/__debug__/",
    ]

    def process_request(self, request):
        """Set tenant hospital context on each request."""
        if request.user and request.user.is_authenticated:
            request.user_roles = request.user.get_role_names()

            request.source_user = None
            request.source_user_profile = None
            if request.user.is_source_user():
                profile = request.user.get_source_user_profile_active()
                if profile:
                    request.source_user = profile
                    request.source_user_profile = profile

            if request.user.is_px_admin():
                hospital_id = request.session.get("selected_hospital_id")
                if hospital_id:
                    from apps.organizations.models import Hospital

                    try:
                        request.tenant_hospital = Hospital.objects.get(id=hospital_id)
                    except Hospital.DoesNotExist:
                        request.tenant_hospital = None
                        request.session.pop("selected_hospital_id", None)
                else:
                    request.tenant_hospital = None
            else:
                request.tenant_hospital = request.user.hospital
        else:
            request.tenant_hospital = None
            request.user_roles = []
            request.source_user = None
            request.source_user_profile = None

        return None

    def process_view(self, request, view_func, view_args, view_kwargs):
        """Redirect PX admins without hospital to select-hospital page."""
        if not request.user or not request.user.is_authenticated:
            return None

        if not request.user.is_px_admin():
            return None

        if request.tenant_hospital:
            return None

        path = request.path
        for exempt_path in self.EXEMPT_PATHS:
            if path.startswith(exempt_path):
                return None

        if request.headers.get("x-requested-with") == "XMLHttpRequest":
            return None

        return HttpResponseRedirect(reverse("core:select_hospital"))


class DepartmentRespondentMiddleware(MiddlewareMixin):
    """
    Restrict Department Respondent users to only their department detail page,
    inquiry department response pages, and observation department response pages.
    """

    ALLOWED_PATH_PREFIXES = [
        "/",
        "/accounts/logout/",
        "/accounts/password_reset/",
        "/accounts/reset/",
        "/core/select-hospital/",
        "/organizations/departments/",
        "/inquiries/",
        "/observations/",
        "/api/",
        "/health/",
        "/admin/",
        "/__debug__/",
        "/i18n/",
        "/static/",
    ]

    def process_view(self, request, view_func, view_args, view_kwargs):
        if not request.user or not request.user.is_authenticated:
            return None

        if not request.user.is_champion():
            return None

        if request.user.is_px_admin() or request.user.is_hospital_admin() or request.user.is_department_manager() or request.user.is_director():
            return None

        if request.headers.get("x-requested-with") == "XMLHttpRequest":
            return None

        path = request.path

        if path == "/":
            return None

        for prefix in self.ALLOWED_PATH_PREFIXES:
            if path.startswith(prefix):
                if path.startswith("/organizations/departments/"):
                    if "set-champion" in path or "edit" in path or "delete" in path:
                        from django.http import HttpResponseForbidden

                        return HttpResponseForbidden()
                    return None
                if path.startswith("/inquiries/"):
                    if not path.endswith("/department-response/"):
                        from apps.complaints.models import Inquiry

                        pk = view_kwargs.get("pk")
                        if pk:
                            try:
                                inquiry = Inquiry.objects.get(pk=pk)
                                user_dept = request.user.department
                                if inquiry.department == user_dept or inquiry.outgoing_department == user_dept:
                                    return None
                            except Inquiry.DoesNotExist:
                                pass
                        from django.http import HttpResponseForbidden

                        return HttpResponseForbidden()
                    return None
                if path.startswith("/observations/"):
                    if path.endswith("/department-response/"):
                        from apps.observations.models import Observation

                        pk = view_kwargs.get("pk")
                        if pk:
                            try:
                                observation = Observation.objects.get(pk=pk)
                                user_dept = request.user.department
                                if observation.assigned_department == user_dept:
                                    return None
                            except Observation.DoesNotExist:
                                pass
                        from django.http import HttpResponseForbidden

                        return HttpResponseForbidden()
                    pk = view_kwargs.get("pk")
                    if pk:
                        from apps.observations.models import Observation

                        try:
                            observation = Observation.objects.get(pk=pk)
                            user_dept = request.user.department
                            if observation.assigned_department == user_dept:
                                return None
                        except Observation.DoesNotExist:
                            pass
                    from django.http import HttpResponseForbidden

                    return HttpResponseForbidden()
                return None

        from django.http import HttpResponseForbidden

        return HttpResponseForbidden()
