package grpc

import (
	"context"
	"fmt"

	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/logger"

	"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
	"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

type presetDailOption struct{}

func PresetDailOption() presetDailOption {
	return presetDailOption{}
}

func (o presetDailOption) Default() []grpc.DialOption {
	opts := []grpc.DialOption{
		o.WithInsecure(),
		o.WithLoadBalance(),
		o.WithTrace(),
	}
	return opts
}

func (o presetDailOption) WithInsecure() grpc.DialOption {
	return grpc.WithTransportCredentials(insecure.NewCredentials())
}

func (o presetDailOption) WithLoadBalance() grpc.DialOption {
	return grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`)
}

func (o presetDailOption) WithTrace() grpc.DialOption {
	return grpc.WithStatsHandler(otelgrpc.NewClientHandler())
}

func (o presetDailOption) WithLog() []grpc.DialOption {
	return []grpc.DialOption{
		grpc.WithChainUnaryInterceptor(
			logging.UnaryClientInterceptor(InterceptorLogger()),
		),
		grpc.WithChainStreamInterceptor(
			logging.StreamClientInterceptor(InterceptorLogger()),
		),
	}
}

func InterceptorLogger() logging.Logger {
	return logging.LoggerFunc(func(ctx context.Context, lvl logging.Level, msg string, fields ...any) {
		l := logger.FromContext(ctx, fields...)

		switch lvl {
		case logging.LevelDebug:
			l.V(4).Info(msg)
		case logging.LevelInfo:
			l.Info(msg)
		case logging.LevelWarn:
			l.Info(msg)
		case logging.LevelError:
			l.Error(fmt.Errorf("grpc error"), msg)
		default:
			panic(fmt.Sprintf("unknown level %v", lvl))
		}
	})
}
