package app

import (
	"context"
	"strings"

	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"go.uber.org/dig"
	"google.golang.org/grpc"
	healthpb "google.golang.org/grpc/health/grpc_health_v1"

	authconsts "github.com/tidbcloud/aisupport/packages/sdk-go/infra/auth/consts"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/logger"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/rpcserver"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/rpcserver/middlewares"
	"github.com/tidbcloud/aisupport/services/agent-gateway/config"
)

type HandlerResult struct {
	dig.Out

	Handler        rpcserver.RPCHandler     `group:"rpcHandlers"`
	GatewayHandler rpcserver.GatewayHandler `group:"rpcGatewayHandlers"`
}

type RPCServerParam struct {
	dig.In

	Config   *config.RootConfig
	Handlers []rpcserver.RPCHandler `group:"rpcHandlers"`
}

type RPCGatewayServerParam struct {
	dig.In

	Config   *config.RootConfig
	Handlers []rpcserver.GatewayHandler `group:"rpcGatewayHandlers"`
}

func NewRPCServer(param RPCServerParam) (*rpcserver.RPCServer, error) {
	return rpcserver.NewRPCServer(rpcserver.RPCServerParam{
		Address: param.Config.RPCServer.Address,
		Logger:  logger.Logger,
		ServerOptions: []grpc.ServerOption{
			(&middlewares.LogMetricMiddlewareBuilder{
				Request: middlewares.RequestLoggerOptions{
					Logger:     logger.Logger,
					LogPayload: false,
					FilterFunc: rpcLogFilter,
				},
			}).Build(),
		},
		Handlers: param.Handlers,
		Tracing:  true,
	})
}

func rpcLogFilter(_ context.Context, _ any, info *grpc.UnaryServerInfo) bool {
	return info.FullMethod == healthpb.Health_Check_FullMethodName
}

func NewRPCGatewayServer(param RPCGatewayServerParam) (*rpcserver.RPCGatewayServer, error) {
	return rpcserver.NewRPCGatewayServer(rpcserver.RPCGatewayServerParam{
		Address:      param.Config.RPCGatewayServer.Address,
		RPCAddress:   param.Config.RPCGatewayServer.RPCAddress,
		Logger:       logger.Logger,
		ErrorHandler: rpcserver.GatewayErrorHandler,
		TraceName:    "agent-gateway",
		Handlers:     param.Handlers,
		Middlewares:  []rpcserver.HTTPMiddleware{middlewares.CorsMiddleware},
		MuxOptions: []runtime.ServeMuxOption{
			runtime.WithIncomingHeaderMatcher(incomingHeaderMatcher),
		},
	})
}

func incomingHeaderMatcher(key string) (string, bool) {
	if strings.EqualFold(key, authconsts.HeaderOperator) {
		return strings.ToLower(authconsts.HeaderOperator), true
	}
	if strings.EqualFold(key, "X-Request-ID") {
		return "x-request-id", true
	}
	return runtime.DefaultHeaderMatcher(key)
}
