from django.http import JsonResponse
from django.utils.deprecation import MiddlewareMixin
from django.core.cache import cache
from questbanker_api.utils import get_current_user
from savings.savings_helper import update_savings_account_statuses
import time

class PartnerAccessMiddleware(MiddlewareMixin):
    """
    Middleware to restrict partner users to specific endpoints
    """
    
    ALLOWED_PARTNER_ENDPOINTS = [
        '/api/uncdf-dashboard/',
        '/api/token-auth/',
        '/api/verify-otp/',
        '/admin/',  # Allow admin access for superusers
    ]
    
    def process_request(self, request):
        # Skip for non-authenticated users
        if not hasattr(request, 'user') or not request.user.is_authenticated:
            return None
            
        # Skip for superusers
        if request.user.is_superuser:
            return None
            
        # Check if user is a partner
        try:
            from users.models import UserAssignedRole
            user_role = UserAssignedRole.objects.filter(
                user=request.user,
                is_active=True
            ).first()
            
            if not user_role:
                return None  # Not a partner, allow normal access
                
            role = user_role.assigned_role
            if role.role_type == 'partner':
                current_path = request.path_info
                print(f"PartnerAccessMiddleware: User {request.user.username} accessing {current_path}")
                
                # Check if current endpoint is allowed
                is_allowed = any(
                    current_path.startswith(endpoint) 
                    for endpoint in self.ALLOWED_PARTNER_ENDPOINTS
                )
                
                print(f"PartnerAccessMiddleware: Is allowed: {is_allowed}")
                
                if not is_allowed:
                    print(f"PartnerAccessMiddleware: Blocking access to {current_path}")
                    return JsonResponse({
                        'error': 'Access denied. Partner users can only access the UNCDF dashboard.',
                        'allowed_endpoints': self.ALLOWED_PARTNER_ENDPOINTS,
                        'current_path': current_path,
                        'user_role': role.role_name,
                        'partner_name': role.partner_name
                    }, status=403)
                    
        except Exception as e:
            # Log error but don't block access
            print(f"PartnerAccessMiddleware error: {e}")
            pass
            
        return None


class SlowRequestMiddleware(MiddlewareMixin):
    """
    Middleware to log slow requests
    """
    
    def process_request(self, request):
        request.start_time = time.time()
        return None

    def process_response(self, request, response):
        if hasattr(request, 'start_time'):
            duration = time.time() - request.start_time
            if duration > 2.0:  # Log requests slower than 2 seconds
                with open('logs/slow_requests.log', 'a') as f:
                    f.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {request.method} {request.path} - {duration:.2f}s\n")
        return response


class SavingsAccountLifecycleMiddleware(MiddlewareMixin):
    """
    Opportunistically refresh savings account lifecycle states for the
    current organisation so activation/dormancy changes do not depend only
    on an external cron job being triggered.
    """

    CACHE_KEY_TEMPLATE = "savings-account-lifecycle-sync:{organisation_id}"
    SYNC_INTERVAL_SECONDS = 60

    def _get_organisation_id(self, request):
        organisation_id = get_current_user(request, 'organisation_id', None)
        if organisation_id and not isinstance(organisation_id, dict):
            return organisation_id

        user_branch = getattr(request.user, 'user_organisation_branch', None)
        if user_branch is not None:
            return getattr(user_branch, 'branch_organisation_id', None)

        return None

    def process_request(self, request):
        if request.method == "OPTIONS":
            return None

        if not hasattr(request, 'user') or not request.user.is_authenticated:
            return None

        if not request.path_info.startswith('/api/'):
            return None

        try:
            organisation_id = self._get_organisation_id(request)
            if not organisation_id:
                return None

            cache_key = self.CACHE_KEY_TEMPLATE.format(organisation_id=organisation_id)
            if cache.add(cache_key, True, timeout=self.SYNC_INTERVAL_SECONDS):
                update_savings_account_statuses(organisation_id=organisation_id)
        except Exception as e:
            # Log the failure but never block the request path.
            print(f"SavingsAccountLifecycleMiddleware error: {e}")

        return None
