package grpc_http

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

	"github.com/tidbcloud/dataflow-service/pkg/account/accountdb"

	"github.com/tidbcloud/dataflow-service/internal/config"
	pkg_http "github.com/tidbcloud/dataflow-service/pkg/grpc/http"
	"github.com/tidbcloud/pkgv2/auth/auth0"
	"github.com/tidbcloud/pkgv2/log"
	"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) {
		// try to get requestid from ctx for compatible with grpc-gateway
		ctx = passAuthTypeKeyIntoContext(ctx)
		ctx = passAuthTokenClaimKeyIntoContext(ctx)
		ctx = passAuthUserIDKeyIntoContext(ctx)
		ctx = passAuthOperatorIpIntoContext(ctx)
		return handler(ctx, req)
	}
}

func passAuthUserIDKeyIntoContext(ctx context.Context) context.Context {
	value := pkg_http.FirstHeader(ctx, strings.ToLower(string(auth0.AuthUserIDKey)))
	ctx = context.WithValue(ctx, auth0.AuthUserIDKey, &value)
	return ctx
}

func passAuthTokenClaimKeyIntoContext(ctx context.Context) context.Context {
	value := pkg_http.FirstHeader(ctx, strings.ToLower(string(auth0.AuthTokenClaimKey)))
	user := new(accountdb.User)
	err := json.Unmarshal([]byte(value), user)
	if err == nil {
		ctx = context.WithValue(ctx, auth0.AuthTokenClaimKey, user)
	} else {
		log.Warn(ctx, "get grpc header AuthTokenClaimKey value", zap.String("AuthTokenClaimKey", value))
	}
	return ctx
}

func passAuthTypeKeyIntoContext(ctx context.Context) context.Context {
	value := pkg_http.FirstHeader(ctx, strings.ToLower(string(auth0.AuthTypeKey)))
	ctx = context.WithValue(ctx, auth0.AuthTypeKey, value)
	return ctx
}

func passAuthOperatorIpIntoContext(ctx context.Context) context.Context {
	value := pkg_http.FirstHeader(ctx, strings.ToLower(string(config.ApiOperatorIP)))
	ctx = context.WithValue(ctx, config.ApiOperatorIP, value)
	return ctx
}
