package mastermgr

import (
	"context"
	"strconv"
	"time"

	"github.com/go-logr/logr"
	"sigs.k8s.io/controller-runtime/pkg/client"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	compatk8s "github.com/tidbcloud/infra-provider/pkg/compat/k8s/dataplane"
	infrautil "github.com/tidbcloud/infra-provider/pkg/util"

	"github.com/tidbcloud/eks-provider/api/v1alpha1"
	"github.com/tidbcloud/eks-provider/controllers/tiflow/task"
	"github.com/tidbcloud/infra-provider/pkg/config"
	"github.com/tidbcloud/infra-provider/pkg/k8s"
	"github.com/tidbcloud/infra-provider/pkg/namer"
	"github.com/tidbcloud/infra-provider/pkg/util"
)

type Context struct {
	// Injected from the caller
	Logger logr.Logger
	Local  client.Client
	Remote k8s.ClientGetter

	Config config.RootConfig
	Namer  *namer.TiflowNamer

	TiflowClusterMasterManager    *v1alpha1.TiflowClusterMasterManager
	TiflowClusterExecutorList     []v1alpha1.TiflowClusterExecutor
	ActiveTiflowClusterMasterList []v1alpha1.TiflowClusterMaster
	Network                       *cloudv1.Network

	Account *cloudv1.Account
}

func (c *Context) Default() *Context {
	c.Remote = &k8s.EmptyGetter{}
	c.Namer = namer.NewTiflowNamer().
		WithNetworkName(c.Network.Name).
		WithNetworkNamespace(c.Network.Namespace).
		WithTiflowNamespace(task.GetTiflowNamespace(c.Network)).
		WithTiflowClusterName("shared-" + strconv.FormatInt(time.Now().Unix(), 10) + "-" + infrautil.FnvHash(namer.UniqueIdentifier(c.Network.ObjectMeta))).
		WithTiflowClusterMasterManagerType(v1alpha1.DefaultSharedTiflowMasterManager.String()).
		WithTiflowClusterMasterManagerName(
			namer.UniqueIdentifier(c.Network.ObjectMeta, namer.WithPrefix(v1alpha1.DefaultSharedTiflowMasterManager.String())))
	return c
}

func (c *Context) SetRemoteClient(ctx context.Context) error {
	scheme, err := k8s.TiflowOperatorScheme()
	if err != nil {
		return err
	}
	g, err := compatk8s.NetworkClientGetter(ctx, c.Local, c.Network, scheme)
	if err != nil {
		return err
	}
	c.Remote = k8s.NewCacheClientGetter(g)
	return nil
}

func (c *Context) HasActiveMaster() bool {
	return len(c.ActiveTiflowClusterMasterList) > 0
}

func (c *Context) HasActiveExecutor() bool {
	return len(c.TiflowClusterExecutorList) > 0
}

func (c *Context) GetTenantID() string {
	return util.GetLabel(c.Network, cloudv1.TenantTagKey)
}

func (c *Context) GetProjectID() string {
	return util.GetLabel(c.Network, cloudv1.ProjectTagKey)
}
