from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
from rest_framework import status
from django.http import Http404
from django.core.exceptions import PermissionDenied


def custom_exception_handler(exc, context):
    """
    Wraps all DRF error responses in a standard envelope:
    {
        "error": {
            "code": "STRING",
            "message": "Human-readable message",
            "details": [{"field": "name", "issue": "reason"}, ...]
        }
    }
    """
    response = drf_exception_handler(exc, context)

    if response is None:
        return response

    error_code = _get_error_code(response.status_code)
    details = _parse_details(response.data)

    message = _get_message(response.status_code, details)

    response.data = {
        "error": {
            "status_code": response.status_code,
            "code": error_code,
            "message": message,
            "details": details,
        }
    }
    return response


def _get_error_code(status_code):
    mapping = {
        400: "BAD_REQUEST",
        401: "UNAUTHORIZED",
        403: "FORBIDDEN",
        404: "NOT_FOUND",
        405: "METHOD_NOT_ALLOWED",
        409: "CONFLICT",
        429: "THROTTLED",
    }
    return mapping.get(status_code, "SERVER_ERROR")


def _get_message(status_code, details):
    mapping = {
        400: "Validation failed.",
        401: "Authentication credentials were not provided or are invalid.",
        403: "You do not have permission to perform this action.",
        404: "The requested resource was not found.",
        405: "HTTP method not allowed.",
        429: "Request was throttled.",
    }
    return mapping.get(status_code, "An unexpected error occurred.")


def _parse_details(data):
    """Convert DRF's error dict/list into a flat list of {field, issue} dicts."""
    details = []
    if isinstance(data, dict):
        for field, issues in data.items():
            if isinstance(issues, list):
                for issue in issues:
                    details.append({"field": field, "issue": str(issue)})
            else:
                details.append({"field": field, "issue": str(issues)})
    elif isinstance(data, list):
        for item in data:
            details.append({"field": "non_field_errors", "issue": str(item)})
    return details
