from rest_framework import renderers, status


def get_status(code):
    """
    Get the human-readable SNAKE_CASE version of an HTTP status code.

    Args:
        code: The HTTP status code to be translated.

    Returns:
        str: The human-readable status in SNAKE_CASE.
    """
    for name, val in status.__dict__.items():
        if not callable(val) and code is val:
            return name.replace("HTTP_%s_" % code, "")
    return "UNKNOWN"


def get_error_message(error_dict):
    """
    Extract the error message from a nested error dictionary.

    Args:
        error_dict: A nested dictionary containing error messages.

    Returns:
        str: The extracted error message.
    """
    try:
        response = error_dict[next(iter(error_dict))]
        if isinstance(response, dict):
            response = get_error_message(response)
        elif isinstance(response, list):
            response_message = response[0]
            if isinstance(response_message, dict):
                response = get_error_message(response_message)
            else:
                response = response[0]
        return response
    except:
        return error_dict


class CustomRenderer(renderers.JSONRenderer):
    """
    A custom JSON renderer to modify the API response format.

    Methods:
        render(data, accepted_media_type, renderer_context): Render the data in a modified format.
    """

    def render(self, data, accepted_media_type=None, renderer_context=None):
        """
        Modify the API response format.

        Args:
            data: The data to be rendered in the response.
            accepted_media_type: The accepted media type for the response.
            renderer_context: The context of the renderer.

        Returns:
            str: The modified JSON response.
        """

        if data is None:
            data = {}

        response = renderer_context["response"]

        # Modify the response into a cohesive response format
        modified_data = {
            "code": response.status_code,
            "status": get_status(response.status_code),
        }


        if data.get("message", None) is not None:
            modified_data["message"] = data.get("message", None)

        if status.is_client_error(response.status_code) or status.is_server_error(
            response.status_code
        ):
            if isinstance(data, list) and data:
                if isinstance(data[0], dict):
                    message = (get_error_message(data),)
                elif isinstance(data[0], str):
                    message = data[0]
            if isinstance(data, dict):
                error_message = get_error_message(data)
                if list(data.keys()) and error_message in [
                    "This field may not be blank.",
                    "This field may not be null.",
                ]:
                    message = (
                        list(data.keys())[0].capitalize().replace("_", " ")
                        + " "
                        + get_error_message(data).lower()
                    )
                else:
                    message = get_error_message(data)
            modified_data["message"] = message
        else:
            if isinstance(data, dict):
                if data.get("results") is not None and isinstance(
                    data.get("results"), list
                ):
                    modified_data["count"] = data.get("count")
                    modified_data["next"] = data.get("next")
                    modified_data["previous"] = data.get("previous")

                message = data.pop("message_", None)
                if message:
                    modified_data["message"] = message
                if data.get("results") is not None:
                    modified_data["data"] = data.get("results")
                else:
                    modified_data["data"] = data
            else:
                modified_data["data"] = data
        if "message" in modified_data:
            modified_data["message"] = modified_data["message"].capitalize()
        return super().render(modified_data, accepted_media_type, renderer_context)
