package interceptor

import (
	"bytes"
	"errors"
	"io"
	"net/http"

	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"google.golang.org/protobuf/encoding/protojson"
)

// same setting as
// https://github.com/tidbcloud/tidb-management-service/blob/main/serverless-regional-service/pkg/utils/gwruntime_helper.go#L58
var jsonpb = &runtime.JSONPb{
	MarshalOptions: protojson.MarshalOptions{
		UseProtoNames:   false,
		EmitUnpopulated: true,
	},
	UnmarshalOptions: protojson.UnmarshalOptions{
		DiscardUnknown: true,
	},
}

// JSONPB encode json to proto.Message
var JSONPb = jsonpbBinding{}

type jsonpbBinding struct{}

func (jsonpbBinding) Name() string {
	return "jsonpb"
}

func (b jsonpbBinding) Bind(req *http.Request, obj interface{}) error {
	if req == nil || req.Body == nil {
		return errors.New("invalid request")
	}
	return decodeJSONPB(req.Body, obj)
}

func (jsonpbBinding) BindBody(body []byte, obj interface{}) error {
	return decodeJSONPB(bytes.NewReader(body), obj)
}

func decodeJSONPB(r io.Reader, obj any) error {
	return jsonpb.NewDecoder(r).Decode(obj)
}
