from django.shortcuts import render
from django.http import HttpResponse
from django.conf import settings
from utils.models import SystemSetting
import time
import os
import mimetypes
from django.http import HttpResponse, Http404
from django.core.exceptions import PermissionDenied
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt


class MaintenanceModeMiddleware:
    """Middleware to handle maintenance mode"""
    
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Check if maintenance mode is enabled
        maintenance_mode = SystemSetting.get_bool('maintenance_mode', False)
        
        if maintenance_mode:
            # Allow access to maintenance page and admin
            if request.path in ['/maintenance/', '/admin/', '/admin/login/'] or request.user.is_staff:
                return self.get_response(request)
            
            # Show maintenance page for all other requests
            return render(request, 'utils/maintenance.html', {
                'maintenance_message': SystemSetting.get_setting('maintenance_message', 'System is under maintenance. Please try again later.')
            })
        
        return self.get_response(request)


class SessionTimeoutMiddleware:
    """Middleware to handle session timeout based on settings"""
    
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.user.is_authenticated:
            # Get session timeout from settings
            session_timeout_minutes = SystemSetting.get_int('session_timeout_minutes', 30)
            
            # Check if session has expired
            last_activity = request.session.get('last_activity')
            if last_activity:
                timeout_seconds = session_timeout_minutes * 60
                if time.time() - last_activity > timeout_seconds:
                    # Session expired, logout user
                    from django.contrib.auth import logout
                    logout(request)
                    from django.contrib import messages
                    messages.warning(request, 'Your session has expired. Please log in again.')
                    from django.shortcuts import redirect
                    return redirect('users:login')
            
            # Update last activity
            request.session['last_activity'] = time.time()
        
        return self.get_response(request) 


class MediaFileMiddleware:
    """
    Middleware to serve media files in production when web server fails to serve them
    """
    
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # Check if this is a media file request
        if request.path.startswith('/media/'):
            return self.serve_media_file(request)
        
        return self.get_response(request)
    
    def serve_media_file(self, request):
        """Serve media files with security checks"""
        # Extract file path from URL
        file_path = request.path.replace('/media/', '')
        
        # Security: Prevent directory traversal
        if '..' in file_path or file_path.startswith('/'):
            raise Http404("Invalid file path")
        
        # Construct full path
        full_path = os.path.join(settings.MEDIA_ROOT, file_path)
        
        # Security: Ensure file is within MEDIA_ROOT
        if not os.path.abspath(full_path).startswith(os.path.abspath(settings.MEDIA_ROOT)):
            raise Http404("File not found")
        
        # Check if file exists
        if not os.path.exists(full_path) or not os.path.isfile(full_path):
            raise Http404("File not found")
        
        # Basic permission check for KYC documents
        if 'kyc/' in file_path and not request.user.is_authenticated:
            raise PermissionDenied("Authentication required")
        
        # Determine content type
        content_type, _ = mimetypes.guess_type(full_path)
        if content_type is None:
            content_type = 'application/octet-stream'
        
        # Serve the file
        try:
            with open(full_path, 'rb') as f:
                response = HttpResponse(f.read(), content_type=content_type)
                response['Content-Disposition'] = f'inline; filename="{os.path.basename(full_path)}"'
                return response
        except IOError:
            raise Http404("File not found") 