package interceptor

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"strings"

	appconfig "github.com/tidbcloud/dataflow-service/app/config"
	"github.com/tidbcloud/dataflow-service/pkg/account/accountdb"
	pkg_http "github.com/tidbcloud/dataflow-service/pkg/grpc/http"
	"github.com/tidbcloud/dataflow-service/pkg/log"
	"github.com/tidbcloud/pkgv2/auth/auth0"
	"go.uber.org/zap"
	"google.golang.org/grpc"
)

func UserPasserUnaryServerInterceptor() grpc.UnaryServerInterceptor {
	return func(ctx context.Context, req interface{},
		info *grpc.UnaryServerInfo, handler grpc.UnaryHandler,
	) (interface{}, error) {
		ctx = passDataflowUserIntoContext(ctx)
		return handler(ctx, req)
	}
}

func passDataflowUserIntoContext(ctx context.Context) context.Context {
	userValue := getUserValue(ctx)
	if userValue == "" {
		return ctx
	}
	user := &accountdb.User{}
	err := json.Unmarshal([]byte(userValue), user)
	if err != nil {
		log.GetLogger(ctx).Warn("failed to unmarshal user", zap.Error(err))
		return ctx
	}
	ctx = context.WithValue(ctx, auth0.AuthTokenClaimKey, user)
	return ctx
}

func getUserValue(ctx context.Context) string {
	value := pkg_http.FirstHeader(ctx, strings.ToLower(appconfig.GrpcGatewayDataflowUserKey))
	if value != "" {
		decodedBytes, err := base64.StdEncoding.DecodeString(value)
		if err != nil {
			log.GetLogger(ctx).Warn("failed to decode user", zap.Error(err))
			return ""
		}
		return string(decodedBytes)
	}

	value = pkg_http.FirstHeader(ctx, strings.ToLower(string(auth0.AuthTokenClaimKey)))
	if value == "" {
		return ""
	}
	log.GetLogger(ctx).Info("get grpc header AuthTokenClaimKey value")
	return value
}
