package openapi

import (
	"context"
	"fmt"
	"time"

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

	openapizerov1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/zero/v1beta1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/app/common"
	tidbmgmtservice "github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/infra/mgmtservicecmock"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/pkg/apimiddleware/reqmodifier"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/pkg/config"
)

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

	if fakeGRPC {
		tidbmgmtservice.SetupFakeMgmtGRPCServer(address)
		return nil
	}

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

	err = registerZeroV1beta1Handlers(eng, conn)
	if err != nil {
		return errtrace.Wrap(fmt.Errorf("failed to register gRPC handlers: %w", err))
	}

	return nil
}

// registerZeroV1beta1Handlers registers the zero open-API handlers.
func registerZeroV1beta1Handlers(
	eng *gin.Engine,
	conn *grpc.ClientConn,
) error {
	gwmux := common.MakeGatewayMux()

	if err := openapizerov1beta1.RegisterZeroInstanceServiceHandler(context.Background(), gwmux, conn); err != nil {
		return errtrace.Wrap(err)
	}

	openapi := eng.Group("/zero/v1beta1")

	openapi.Use(reqmodifier.ServePathStartFromAny)
	openapi.Any("/*any", gin.WrapF(gwmux.ServeHTTP))

	return nil
}
