package service

import (
	coreapi "github.com/tidbcloud/core-svc/idl/pbgen/proto/core"
	"github.com/tidbcloud/tiinf/tiinf"
	tigrpc "github.com/tidbcloud/tiinf/transport/tigrpc/server"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/reflection"
	"google.golang.org/grpc/status"

	tidbmgmtservicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"github.com/tidbcloud/tidb-management-service/tempo-proxy/utils"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/grpc"
)

func RunGrpcServer(port int, name string) error {
	inf, _, _, err := NewGrpcServer(port, name)
	if err != nil {
		return err
	}
	return inf.Run()
}

func NewGrpcServer(port int, name string) (tiinf.TiInf, *MockClusterService, *utils.ApiCallRecorder, error) {
	recorder := utils.NewApiCallRecorder()
	inf := tiinf.NewInf()
	err := inf.Init(
		tiinf.WithConfig(&tiinf.Config{
			TiInfConfig: tiinf.TiInfConfig{
				LocalMode: true,
				GrpcServerConfig: tiinf.GrpcServerConfig{
					Enable: true,
					Port:   uint16(port),
				},
				// Port can't be zero even gin service is disabled
				GinConfig: tiinf.GinConfig{
					Port: uint16(8080),
				},
				// Port can't be zero even metrics service is disabled
				MetricsConfig: tiinf.MetricsConfig{
					Port: uint16(9090),
				},
			},
		}),
		tiinf.WithGrpcOptions(tigrpc.WithUnaryInterceptors(
			grpc.BuildBizErrTransformInterceptor(func(resp any, err bizerr.BizError) (any, error) {
				return resp, status.Error(codes.Code(err.ErrCode()), err.ErrMsg())
			}),
		)),
		tiinf.WithGrpcOptions(tigrpc.WithUnaryInterceptors(
			recorder.UnaryServerInterceptor(),
		)),
	)
	if err != nil {
		return nil, nil, nil, err
	}

	gs := inf.GrpcServer()
	reflection.Register(gs)

	svc := NewMockClusterService(name)
	coreapi.RegisterCoreServiceServer(gs, svc.CoreSvc)
	tidbmgmtservicev1.RegisterClusterServiceServer(gs, svc)
	return inf, svc, recorder, nil
}
