"""
API request/response logging middleware.
Logs /api/ requests with sanitized payload (no passwords) and response status.
"""
import json
import logging
import copy

logger = logging.getLogger('api')

# Fields to redact from logs
SENSITIVE_KEYS = frozenset({'password', 'token', 'secret', 'authorization'})


def _sanitize(data):
    """Remove sensitive fields from dict for logging."""
    if not isinstance(data, dict):
        return str(data)[:500]
    out = copy.deepcopy(data)
    for key in list(out.keys()):
        key_lower = key.lower()
        if any(s in key_lower for s in SENSITIVE_KEYS):
            out[key] = '***'
    return out


class APILoggingMiddleware:
    """Log API requests and responses."""

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if not request.path.startswith('/api/'):
            return self.get_response(request)

        # Build log context (sanitize body)
        try:
            if request.content_type and 'json' in request.content_type and request.body:
                body = json.loads(request.body.decode('utf-8', errors='replace'))
                body_safe = _sanitize(body)
            else:
                body_safe = None
        except Exception:
            body_safe = '(parse error)'

        # Process request
        response = self.get_response(request)

        # Log after response (pass payload for debugging, passwords are redacted)
        user = str(request.user) if request.user.is_authenticated else 'anon'
        ip = self._get_client_ip(request)
        try:
            body_str = json.dumps(body_safe) if body_safe is not None else '-'
        except (TypeError, ValueError):
            body_str = str(body_safe)[:200]
        logger.info(
            'API %s %s -> %s | user=%s ip=%s | body=%s',
            request.method,
            request.path,
            response.status_code,
            user,
            ip,
            body_str,
        )
        return response

    def _get_client_ip(self, request):
        xff = request.META.get('HTTP_X_FORWARDED_FOR')
        if xff:
            return xff.split(',')[0].strip()
        return request.META.get('REMOTE_ADDR', '')
