"""
Decorators for feature-based access control with role hierarchy
"""
from functools import wraps
from django.shortcuts import render
from django.http import JsonResponse
from django.conf import settings

from ldc_dashboard_rbac.permissions import user_has_feature_permission, get_rbac_config, is_superadmin_user, is_admin_user
from ldc_dashboard_rbac.constants import (
    APIDetection, HTTPStatus, TemplatePaths, ErrorMessages, LogMessages, 
    PermissionLevels, SettingsKeys
)
import logging

logger = logging.getLogger(__name__)


def _is_api_request(request):
    """
    Improved detection for API requests.
    Returns True if the request appears to be from an API client.
    """
    # Check for common API indicators
    content_type = request.headers.get('Content-Type', '').lower()
    accept = request.headers.get('Accept', '').lower()
    
    # Common API request patterns
    api_indicators = [
        # AJAX requests
        request.headers.get(APIDetection.AJAX_HEADER) == APIDetection.AJAX_VALUE,
        # JSON content type
        APIDetection.JSON_CONTENT_TYPE in content_type,
        # API-specific accept headers
        APIDetection.JSON_CONTENT_TYPE in accept,
        APIDetection.API_JSON_CONTENT_TYPE in accept,
        # DRF browsable API
        APIDetection.HTML_CONTENT_TYPE not in accept or APIDetection.JSON_CONTENT_TYPE in accept,
        # Common API user agents (partial matches)
        any(agent in request.headers.get('User-Agent', '').lower() 
            for agent in APIDetection.API_USER_AGENTS),
        # API path patterns (customize these based on your URL structure)
        APIDetection.API_URL_PATTERN in request.path.lower(),
    ]
    
    return any(api_indicators)


def _handle_permission_denied(request, error_message, feature_url_name=None, permission_level=None, status_code=HTTPStatus.FORBIDDEN):
    """
    Handle permission denied responses for both web and API requests.
    """
    if _is_api_request(request):
        response_data = {'error': error_message}
        if feature_url_name:
            response_data['feature'] = feature_url_name
        if permission_level:
            response_data['required_permission'] = permission_level
        
        return JsonResponse(response_data, status=status_code)
    
    # Web request - return HTML page
    context = {'error': error_message}
    if feature_url_name:
        context['feature'] = feature_url_name
    if permission_level:
        context['required_permission'] = permission_level
    
    return render(request, TemplatePaths.PERMISSION_DENIED, context, status=status_code)


def feature_required(feature_url_name: str, permission_level: str = PermissionLevels.READ):
    """
    Decorator to check if user has permission for a specific feature.
    Works with both Django views and API endpoints.
    
    Role hierarchy:
    - Superadmin: All access
    - Admin: All access  
    - User: Feature-level access via groups
    
    Usage:
        @feature_required('user_management')
        def my_view(request):
            pass
            
        @feature_required('user_management', PermissionLevels.WRITE)
        def my_api_view(request):
            pass
    """
    def decorator(view_func):
        @wraps(view_func)
        def _wrapped_view(request, *args, **kwargs):
            config = get_rbac_config()
            user_getter = config.get(SettingsKeys.GroupRBAC.USER_GETTER)
            
            if not user_getter:
                logger.error(ErrorMessages.USER_GETTER_NOT_CONFIGURED)
                return _handle_permission_denied(
                    request, 
                    ErrorMessages.CONFIG_NOT_CONFIGURED,
                    status_code=HTTPStatus.INTERNAL_SERVER_ERROR
                )
            
            user = user_getter(request)
            
            # ✅ SUPERADMIN BYPASS: Always allow superadmin access
            if is_superadmin_user(user):
                logger.info(LogMessages.SUPERADMIN_ACCESS_GRANTED.format(user=user, feature_name=feature_url_name) + " via decorator")
                return view_func(request, *args, **kwargs)
            
            # ✅ ADMIN BYPASS: Always allow admin access
            if is_admin_user(user):
                logger.info(LogMessages.ADMIN_ACCESS_GRANTED.format(user=user, feature_name=feature_url_name) + " via decorator")
                return view_func(request, *args, **kwargs)
            
            # Regular permission check for users
            if not user_has_feature_permission(user, feature_url_name, permission_level):
                return _handle_permission_denied(
                    request,
                    ErrorMessages.NO_FEATURE_PERMISSION,
                    feature_url_name,
                    permission_level
                )
            
            return view_func(request, *args, **kwargs)
        
        return _wrapped_view
    return decorator


def admin_required(view_func=None):
    """
    Decorator to check if user is admin or superadmin.
    Works with both Django views and API endpoints.
    
    Usage:
        @admin_required
        def my_admin_view(request):
            pass
    """
    def decorator(func):
        @wraps(func)
        def _wrapped_view(request, *args, **kwargs):
            config = get_rbac_config()
            user_getter = config.get(SettingsKeys.GroupRBAC.USER_GETTER)
            
            if not user_getter:
                logger.error(ErrorMessages.USER_GETTER_NOT_CONFIGURED)
                return _handle_permission_denied(
                    request,
                    ErrorMessages.CONFIG_NOT_CONFIGURED,
                    status_code=HTTPStatus.INTERNAL_SERVER_ERROR
                )
            
            user = user_getter(request)
            
            if not (is_admin_user(user) or is_superadmin_user(user)):
                return _handle_permission_denied(
                    request,
                    ErrorMessages.NO_ADMIN_PERMISSION
                )
            
            return func(request, *args, **kwargs)
        
        return _wrapped_view
    
    if view_func:
        return decorator(view_func)
    return decorator


def superadmin_required(view_func=None):
    """
    Decorator to check if user is superadmin only.
    Works with both Django views and API endpoints.
    
    Usage:
        @superadmin_required
        def my_superadmin_view(request):
            pass
    """
    def decorator(func):
        @wraps(func)
        def _wrapped_view(request, *args, **kwargs):
            config = get_rbac_config()
            user_getter = config.get(SettingsKeys.GroupRBAC.USER_GETTER)
            
            if not user_getter:
                logger.error(ErrorMessages.USER_GETTER_NOT_CONFIGURED)
                return _handle_permission_denied(
                    request,
                    ErrorMessages.CONFIG_NOT_CONFIGURED,
                    status_code=HTTPStatus.INTERNAL_SERVER_ERROR
                )
            
            user = user_getter(request)
            
            if not is_superadmin_user(user):
                return _handle_permission_denied(
                    request,
                    ErrorMessages.NO_SUPERADMIN_PERMISSION
                )
            
            return func(request, *args, **kwargs)
        
        return _wrapped_view
    
    if view_func:
        return decorator(view_func)
    return decorator


# Alias for backward compatibility
feature_permission_required = feature_required