"""
This module provides a custom CSRF middleware that extends
Django's default CsrfViewMiddleware.
It allows for the use of a custom name for the CSRF token,
enhancing the flexibility of CSRF protection in Django applications.
The primary class provided is SecureCsrfMiddleware, which can be
used as a drop-in replacement for Django's default CSRF middleware.
"""

from django.conf import settings
from django.http import FileResponse
from django.middleware.csrf import CsrfViewMiddleware as DjangoCsrfViewMiddleware
from django.utils.safestring import mark_safe


class SecureCsrfMiddleware(DjangoCsrfViewMiddleware):
    """
    SecureCsrfMiddleware extends the default CsrfViewMiddleware from
    Django to allow for a custom CSRF token name.
    It overrides the process_request and process_response methods
    to replace the standard 'csrfmiddlewaretoken'
    with a custom name defined in the class attribute 'secure_csrf_name'.
    This class provides a way to customize the CSRF token name for security
    or organizational preferences without altering the fundamental CSRF
    protection mechanisms.
    """

    # Define 'secure_csrf_name' as a class attribute
    secure_csrf_name = settings.CSRF_INPUT_NAME

    def process_request(self, request):
        """
        Processes incoming requests to replace the standard CSRF token
        name with the custom one.
        It checks for the presence of the custom CSRF token name in the
        POST data and, if found, replaces the default 'csrfmiddlewaretoken'
        with the custom token. This method ensures that the system recognizes
        the token under its new name during the request lifecycle.

        :param request: HttpRequest object representing the current request
        :return: The result of the parent class's process_request method
        """
        request.POST = request.POST.copy()
        if self.secure_csrf_name in request.POST:
            request.POST["csrfmiddlewaretoken"] = request.POST.pop(
                self.secure_csrf_name
            )[0]
        return super().process_request(request)

    def process_response(self, request, response):
        """
        Processes outgoing responses to replace occurrences of the default
        CSRF token name in the HTML content with the custom CSRF token name.
        It ensures that forms rendered in the response HTML use the custom
        token name, maintaining consistency with the request processing and
        providing a seamless experience.

        :param request: HttpRequest object representing the current request
        :param response: HttpResponse object representing the current response
        :return: The result of the parent class's process_response method with
        modified content
        """
        # Check if the response is a FileResponse instance
        if isinstance(response, FileResponse):
            # If it's a FileResponse, return it unmodified
            return response

        # If it's not a FileResponse, proceed with your original processing
        if hasattr(response, "content"):
            response.content = response.content.replace(
                b'name="csrfmiddlewaretoken"',
                mark_safe(f'name="{self.secure_csrf_name}"').encode(),
            )
        return super().process_response(request, response)
