package graphql

import (
	"context"
	"errors"
	"tercul/internal/domain"

	"github.com/99designs/gqlgen/graphql"
	"github.com/vektah/gqlparser/v2/gqlerror"
)

// NewErrorPresenter creates a custom error presenter for gqlgen.
func NewErrorPresenter() graphql.ErrorPresenterFunc {
	return func(ctx context.Context, e error) *gqlerror.Error {
		gqlErr := graphql.DefaultErrorPresenter(ctx, e)

		// Unwrap the error to find the root cause.
		originalErr := errors.Unwrap(e)
		if originalErr == nil {
			originalErr = e
		}

		// Check for custom application errors and format them.
		switch {
		case errors.Is(originalErr, domain.ErrEntityNotFound):
			gqlErr.Message = "The requested resource was not found."
			gqlErr.Extensions = map[string]interface{}{"code": "NOT_FOUND"}
		case errors.Is(originalErr, domain.ErrUnauthorized):
			gqlErr.Message = "You must be logged in to perform this action."
			gqlErr.Extensions = map[string]interface{}{"code": "UNAUTHENTICATED"}
		case errors.Is(originalErr, domain.ErrForbidden):
			gqlErr.Message = "You are not authorized to perform this action."
			gqlErr.Extensions = map[string]interface{}{"code": "FORBIDDEN"}
		case errors.Is(originalErr, domain.ErrValidation):
			// Keep the detailed message from the validation error.
			gqlErr.Message = originalErr.Error()
			gqlErr.Extensions = map[string]interface{}{"code": "VALIDATION_FAILED"}
		case errors.Is(originalErr, domain.ErrConflict):
			gqlErr.Message = "A conflict occurred with the current state of the resource."
			gqlErr.Extensions = map[string]interface{}{"code": "CONFLICT"}
		default:
			// For all other errors, return a generic message to avoid leaking implementation details.
			gqlErr.Message = "An unexpected internal error occurred."
			gqlErr.Extensions = map[string]interface{}{"code": "INTERNAL_SERVER_ERROR"}
		}

		return gqlErr
	}
}