package launcher

import (
	"context"
	"fmt"

	"github.com/gin-gonic/gin"

	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
	"github.com/tidbcloud/account/idl/pbgen/proto/account"
	grpc_errcode "github.com/tidbcloud/account/pkg/grpc/middleware/errcode"
	grpc_server "github.com/tidbcloud/account/pkg/grpc/server"
	"github.com/tidbcloud/tiinf/errs"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"github.com/tidbcloud/tiinf/tiinf"
	tigrpc "github.com/tidbcloud/tiinf/transport/tigrpc/server"
	"go.uber.org/zap"
	"google.golang.org/grpc/health"
	"google.golang.org/grpc/health/grpc_health_v1"
)

type Launcher struct {
	configPath string
	inf        tiinf.TiInf
}

func New(configPath string) *Launcher {
	l := &Launcher{
		configPath: configPath,
	}

	return l
}

func (l *Launcher) Init() {
	ctx := context.Background()

	tilog.Info(ctx, "Initializing gRPC server")
	errorFormat := grpc_errcode.ErrorFormatDefault

	_, err := zap.NewProduction()
	if err != nil {
		panic("failed to init zap logger")
	}

	inf := tiinf.NewInf()
	err = inf.Init(
		tiinf.WithConfigFile(l.configPath),
		tiinf.WithGrpcOptions(
			tigrpc.WithUnaryInterceptors(
				grpc_middleware.ChainUnaryServer(
					errs.UnaryServerInterceptor(),
					grpc_errcode.UnaryServerInterceptor(errorFormat),
				),
			),
			tigrpc.WithStreamInterceptors(
				grpc_middleware.ChainStreamServer(
					grpc_errcode.StreamServerInterceptor(errorFormat),
				),
			),
		),
	)
	if err != nil {
		panic(fmt.Sprintf("failed to init tiinf: %s", err))
	}
	l.inf = inf
	grpc_health_v1.RegisterHealthServer(inf.GrpcServer(), grpc_server.HealthServerNoAuth{
		HealthServer: health.NewServer(),
	})

}

func (l *Launcher) Serve() error {
	return l.inf.Run()
}

func (l *Launcher) RegisterProvider(srv account.AccountAPIServiceServer) {
	account.RegisterAccountAPIServiceServer(l.inf.GrpcServer(), srv)
}

func (l *Launcher) GinEngine() *gin.Engine {
	return l.inf.GinEngine()
}
