package provider

import (
	"context"
	"time"

	"github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
	"github.com/tidbcloud/config-service/sdk/api"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-api/pkg/nodegroup"

	"sigs.k8s.io/controller-runtime/pkg/client"
)

type Provider interface {
	Cluster
	Backup
	Restore
	Cdc
}

type Cluster interface {
	GetComponentNodeLabels(componentType cloudv1.ComponentType) map[string]string
	GetComponentPodLabels(componentType cloudv1.ComponentType) map[string]string
	GetNodeZoneFromLabels(labels map[string]string) string
	GetNodeInstanceTypeFromLabels(labels map[string]string) string
	Overlay(*v1alpha1.TidbCluster) error
}

type Backup interface {
	BuildBackup(*cloudv1.Backup, *cloudv1.Cluster) (*v1alpha1.Backup, error)
	GetBackupClient(context.Context, *cloudv1.Backup) (client.Client, error)
	GetBackupNamespace(context.Context, *cloudv1.Backup) (string, error)
	ClusterReader
}

type Restore interface {
	BuildRestore(*cloudv1.Restore, *cloudv1.Cluster) (*v1alpha1.Restore, error)
	PostRestoreFinished(context.Context, *cloudv1.Restore) error
	ClusterReader
}

type Machine interface {
	FindInstanceType(name string) (cloudv1.InstanceType, error)
}

type ClusterReader interface {
	GetClient(context.Context, *cloudv1.Cluster) (client.Client, error)
	GetKubernetesStatus(*cloudv1.Cluster) (*cloudv1.KubernetesStatus, error)
}

type GitOps interface {
	GetClusterConfig(context.Context, *cloudv1.Cluster) (*api.DescribeClusterConfigOutput, error)
}

type Cdc interface {
	// GetUpstreamClient get k8s client in upstream, will only used for cross region.
	GetCdcUpstreamClient(context.Context, *cloudv1.TiCDC) (client.Client, error)
	// GetClient get k8s client in current network.
	// If cdc used for kafka/mysql, cdc and tidb will deploy in same k8s cluster
	// If cdc used for cross region, cdc will deploy to downstream
	GetCdcClient(context.Context, *cloudv1.Network) (client.Client, error)
	// GetKubernetesStatus get k8s status of cdc.
	GetCdcKubernetesStatus(*cloudv1.Cluster) (*cloudv1.KubernetesStatus, error)
	// CreateCdcNodeGroup create cdc nodegroup. eks provider will create nodegroup in eks cluster. aws/gcp provider will do nothing.
	// aws/gcp provider manage cdc nodes by node controller
	CreateCdcNodeGroup(context.Context, *cloudv1.TiCDC, *nodegroup.Set) (map[string]string, error)
	// DeleteCdcNodeGroup delete cdc nodegroup. eks provider will delete nodegroup in eks cluster. aws/gcp provider will do nothing.
	// aws/gcp provider manage cdc nodes by node controller
	DeleteCdcNodeGroup(context.Context, *cloudv1.TiCDC, *nodegroup.Set) error

	// RequireV1CertManager return true if cdc need cert-manager v1.
	RequireV1CertManager() bool
	// CertificateOptions return certificate options for cdc.
	CertificateOptions() (kind string, name string, d time.Duration)
	// OverrideImage override provider image.
	OverrideImage(cluster *cloudv1.Cluster, imageName string) string
	// GetNetworkProxyBaseURL return the network proxy base url
	GetNetworkProxyBaseURL(_ context.Context, network *cloudv1.Network) (string, error)
}
