package grpctool

import (
	"context"

	"buf.build/go/protovalidate"
	"google.golang.org/grpc"
)

const (
	serverValidationError = "invalid client request"
)

// UnaryServerValidatingInterceptor is a unary client interceptor that performs response validation.
func UnaryServerValidatingInterceptor(v protovalidate.Validator) grpc.UnaryServerInterceptor {
	return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
		err := maybeValidate(v, req, serverValidationError)
		if err != nil {
			return nil, err
		}
		return handler(ctx, req)
	}
}

// StreamServerValidatingInterceptor is a stream client interceptor that performs response stream validation.
func StreamServerValidatingInterceptor(v protovalidate.Validator) grpc.StreamServerInterceptor {
	return func(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
		return handler(srv, &serverRecvValidator{
			ServerStream: stream,
			validator:    v,
		})
	}
}

type serverRecvValidator struct {
	grpc.ServerStream
	validator protovalidate.Validator
}

func (w *serverRecvValidator) RecvMsg(m any) error {
	if err := w.ServerStream.RecvMsg(m); err != nil {
		return err
	}
	return maybeValidate(w.validator, m, serverValidationError)
}
