"""
IP Whitelist Middleware
Only allows requests from internal network
Backend is NOT accessible from public internet
"""

from django.http import HttpResponseForbidden
from django.conf import settings
import ipaddress
import logging

logger = logging.getLogger('django.security')


class IPWhitelistMiddleware:
    """
    Enterprise Security: Only allow requests from whitelisted IPs (internal network)
    This ensures backend API is NEVER directly accessible from internet
    """
    
    def __init__(self, get_response):
        self.get_response = get_response
        
        # Define allowed internal network ranges
        self.allowed_networks = [
            ipaddress.ip_network('127.0.0.0/8'),      # localhost
            ipaddress.ip_network('10.0.0.0/8'),       # Private Class A
            ipaddress.ip_network('172.16.0.0/12'),    # Private Class B
            ipaddress.ip_network('192.168.0.0/16'),   # Private Class C
            ipaddress.ip_network('::1/128'),          # IPv6 localhost
            ipaddress.ip_network('fe80::/10'),        # IPv6 link-local
        ]
        
        # Add custom allowed IPs from settings if any
        custom_allowed = getattr(settings, 'CUSTOM_ALLOWED_IPS', [])
        for ip in custom_allowed:
            try:
                self.allowed_networks.append(ipaddress.ip_network(ip))
            except ValueError:
                logger.warning(f"Invalid IP network in CUSTOM_ALLOWED_IPS: {ip}")

    def __call__(self, request):
        # Get client IP address
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            # Get the first IP in the chain (original client)
            ip = x_forwarded_for.split(',')[0].strip()
        else:
            ip = request.META.get('REMOTE_ADDR')

        # In development, allow all
        if settings.DEBUG:
            return self.get_response(request)

        try:
            client_ip = ipaddress.ip_address(ip)
            
            # Check if IP is in allowed networks
            is_allowed = any(
                client_ip in network 
                for network in self.allowed_networks
            )
            
            if not is_allowed:
                logger.warning(
                    f"Blocked external access attempt from IP: {ip} "
                    f"to path: {request.path}"
                )
                return HttpResponseForbidden(
                    "Access Denied: This API is for internal use only. "
                    "Backend is not accessible from public internet."
                )
                
        except ValueError:
            logger.error(f"Invalid IP address format: {ip}")
            return HttpResponseForbidden("Access Denied: Invalid IP address")

        # IP is whitelisted, process request
        return self.get_response(request)


class SecurityHeadersMiddleware:
    """
    Additional security headers for defense in depth
    """
    
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        
        # Additional security headers
        response['X-Content-Type-Options'] = 'nosniff'
        response['X-Frame-Options'] = 'DENY'
        response['X-XSS-Protection'] = '1; mode=block'
        response['Referrer-Policy'] = 'strict-origin-when-cross-origin'
        response['Permissions-Policy'] = 'geolocation=(), microphone=(), camera=()'
        
        # Remove server identification
        if 'Server' in response:
            del response['Server']
        
        return response

