// Package tidbtools implements the TidbToolsServiceAPI — a thin
// transport-adapter layer over dataflow and cluster-service-ng clients for the
// OPS Portal Tools page. Business logic (if any) lives in converters under
// `devops/api/tidbtools`.
package tidbtools

import (
	"time"

	"github.com/tidbcloud/devops/pkg/infra/clients/coresvccli"
	"github.com/tidbcloud/devops/pkg/infra/clients/dataflowcli"
	"github.com/tidbcloud/devops/pkg/infra/config"
	"github.com/tidbcloud/devops/pkg/service"
	"github.com/tidbcloud/devops/pkg/service/tidbtools/api"
	nextgenglobal "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"

	"go.uber.org/dig"
	"google.golang.org/grpc/codes"
)

// rpcTimeout is the per-call deadline applied to every Tools-page RPC.
// See design doc §4.2 rule 6 (B-Q3 resolved to 5000 ms).
const rpcTimeout = 5 * time.Second

// gRPC status codes returned by the dataflow service for
// "the cluster is not registered in this sub-service's database".
// On the OPS Portal we treat these as "empty list" rather than a 500
// because nightly / freshly-created clusters routinely have no DM /
// Import history yet, and the FE renders the same empty state.
//
// We intentionally do NOT do the same for Backup, Restore, Changefeed
// or Premium DM: those panels are only rendered on cluster types that
// actively use the feature, so a true upstream error there should
// surface as an error rather than be silently presented as empty.
const (
	codeDMClusterNotFound     codes.Code = 49900001
	codeImportClusterNotFound codes.Code = 49900004
)

// ServiceParam is the dig.In for NewService.
type ServiceParam struct {
	dig.In

	Conf     *config.RootConfig
	Dataflow *dataflowcli.DataflowCli
	CoreSvc  *coresvccli.CoreSvcCli
}

// ServiceResult is the dig.Out for NewService.
type ServiceResult struct {
	dig.Out

	API     api.TidbToolsServiceAPI
	Service service.Service `group:"service"`
}

type svc struct {
	*service.JobService

	dataflow      *dataflowcli.DataflowCli
	coreSvc       *coresvccli.CoreSvcCli
	nextGenGlobal nextgenglobal.ClusterServiceClient
	nextGenBackup nextgenglobal.BackupServiceClient
}

// NewService constructs the tidbtools service. It has no persistent
// state and no background jobs in M1; the JobService base is kept only
// for consistency with the other devops services.
func NewService(p ServiceParam) (ServiceResult, error) {
	s := &svc{
		JobService:    service.NewJobService("TidbToolsService"),
		dataflow:      p.Dataflow,
		coreSvc:       p.CoreSvc,
		nextGenGlobal: p.CoreSvc.Mgmt.NextGenCluster,
		nextGenBackup: p.CoreSvc.Mgmt.NextGenBackup,
	}
	return ServiceResult{API: s, Service: s}, nil
}
