"""
Role-based access control decorators for PX360.

Provides decorators to restrict views based on user roles:
- PX Admin
- Hospital Admin
- Department Manager
- PX Employee
- Source User
"""

from functools import wraps
from django.core.exceptions import PermissionDenied
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from django.contrib import messages
from django.utils.translation import gettext_lazy as _


def px_admin_required(view_func):
    """
    Decorator to restrict access to PX Admins only.

    Example:
        @px_admin_required
        def system_settings(request):
            # Only PX Admins can access this
    """

    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        if not request.user.is_px_admin():
            messages.error(request, _("Access denied. PX Admin privileges required."))
            return redirect("analytics:command_center")

        return view_func(request, *args, **kwargs)

    return _wrapped_view


def hospital_admin_required(view_func):
    """
    Decorator to restrict access to Hospital Admins and PX Admins.

    Example:
        @hospital_admin_required
        def hospital_settings(request):
            # Only Hospital Admins and PX Admins can access this
    """

    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        if not (request.user.is_px_admin() or request.user.is_hospital_admin()):
            messages.error(request, _("Access denied. Hospital Admin privileges required."))
            return redirect("analytics:command_center")

        return view_func(request, *args, **kwargs)

    return _wrapped_view


def admin_required(view_func):
    """
    Decorator to restrict access to any Admin (PX, Hospital, or Dept Manager).

    Example:
        @admin_required
        def management_view(request):
            # Any admin can access this
    """

    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        if not (request.user.is_px_admin() or request.user.is_hospital_admin() or request.user.is_department_manager()):
            messages.error(request, _("Access denied. Admin privileges required."))
            return redirect("analytics:command_center")

        return view_func(request, *args, **kwargs)

    return _wrapped_view


def px_employee_required(view_func):
    """
    Decorator to restrict access to PX Management and above.

    Allows: PX Admin, Hospital Admin, Department Manager, PX Management, PX Employee

    Example:
        @px_employee_required
        def complaint_management(request):
            # Staff and admins can access this
    """

    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        user = request.user
        if not (
            user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager() or user.is_px_management() or user.is_px_employee()
        ):
            messages.error(request, _("Access denied. PX Management privileges required."))
            return redirect("analytics:command_center")

        return view_func(request, *args, **kwargs)

    return _wrapped_view


def staff_required(view_func):
    """
    Decorator to restrict access to Hospital Staff (not Source Users).

    Allows all authenticated users except Source Users.

    Example:
        @staff_required
        def internal_tool(request):
            # Any hospital staff can access, but not source users
    """

    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        if request.user.is_source_user():
            messages.error(request, _("Access denied. This page is not available for source users."))
            return redirect("px_sources:source_user_dashboard")

        return view_func(request, *args, **kwargs)

    return _wrapped_view


def source_user_required(view_func):
    """
    Decorator to restrict access to Source Users only.

    Example:
        @source_user_required
        def source_user_dashboard(request):
            # Only source users can access this
    """

    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        if not request.user.is_source_user():
            raise PermissionDenied(_("Access denied. Source user privileges required."))

        # Get source user profile
        profile = request.user.get_source_user_profile_active()
        if not profile:
            messages.error(request, _("Your source user account is inactive. Please contact your administrator."))
            return redirect("accounts:login")

        # Store in request for easy access
        request.source_user = profile
        request.source = profile.source

        return view_func(request, *args, **kwargs)

    return _wrapped_view


def block_source_user(view_func):
    """
    Decorator to BLOCK source users from accessing admin/staff pages.
    Redirects source users to their dashboard instead.

    Example:
        @block_source_user
        def staff_management(request):
            # Source users CANNOT access this
    """

    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        if request.user.is_source_user():
            # Silently redirect to source user dashboard
            return redirect("px_sources:source_user_dashboard")

        return view_func(request, *args, **kwargs)

    return _wrapped_view


def source_user_or_admin(view_func):
    """
    Decorator that allows both source users AND admins.

    Example:
        @source_user_or_admin
        def complaint_detail(request, pk):
            # Both source users and admins can view
    """

    @wraps(view_func)
    @login_required
    def _wrapped_view(request, *args, **kwargs):
        user = request.user

        # Allow admins
        if user.is_px_admin() or user.is_hospital_admin() or user.is_department_manager():
            return view_func(request, *args, **kwargs)

        # Allow active source users
        if user.is_source_user():
            profile = user.get_source_user_profile_active()
            if profile:
                request.source_user = profile
                request.source = profile.source
                return view_func(request, *args, **kwargs)

        raise PermissionDenied(_("Access denied."))

    return _wrapped_view
