package inner

import (
	"context"
	"fmt"
	"time"

	"github.com/gin-gonic/gin"
	"google.golang.org/grpc"

	tidbmgmtservicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/app/common"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/pkg/apimiddleware/reqmodifier"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/pkg/config"
)

func SetupInnerApiHandler(eng *gin.Engine, timeout time.Duration) error {
	address := config.Global().TiDBMgmtServiceConfig.Address

	conn, err := common.CreateGrpcConn(address, timeout)
	if err != nil {
		return fmt.Errorf("failed to dial server: %w", err)
	}

	if err := registerHandlers(eng, conn); err != nil {
		return fmt.Errorf("failed to register gateway: %w", err)
	}
	return nil
}

func registerHandlers(eng *gin.Engine, conn *grpc.ClientConn) error {
	gwmux := common.MakeGatewayMux()

	if err := tidbmgmtservicev1.RegisterRegionServiceHandler(context.Background(), gwmux, conn); err != nil {
		return err
	}
	if err := tidbmgmtservicev1.RegisterClusterServiceHandler(context.Background(), gwmux, conn); err != nil {
		return err
	}
	if err := tidbmgmtservicev1.RegisterDataPlaneServiceHandler(context.Background(), gwmux, conn); err != nil {
		return err
	}
	if err := tidbmgmtservicev1.RegisterSpuServiceHandler(context.Background(), gwmux, conn); err != nil {
		return err
	}
	if err := tidbmgmtservicev1.RegisterVpcServiceHandler(context.Background(), gwmux, conn); err != nil {
		return err
	}
	if err := tidbmgmtservicev1.RegisterPrivateLinkServiceMigrationServiceHandler(context.Background(), gwmux, conn); err != nil {
		return err
	}
	if err := tidbmgmtservicev1.RegisterDataSynchronizationServiceHandler(context.Background(), gwmux, conn); err != nil {
		return err
	}
	if err := tidbmgmtservicev1.RegisterOrganizationConfigServiceHandler(context.Background(), gwmux, conn); err != nil {
		return err
	}
	if err := tidbmgmtservicev1.RegisterFsRegionServiceHandler(context.Background(), gwmux, conn); err != nil {
		return err
	}

	internalApi := eng.Group("/inner/mgmt/v1")

	// strip the base paths of the Kong pre-processed requests, to use the same gRPC handler to serve both OpenAPI and WebUI API.
	internalApi.Use(reqmodifier.ServePathStartFromAny)
	internalApi.Any("/*any", gin.WrapF(gwmux.ServeHTTP))

	return nil
}
