package provider

import (
	"context"
	"fmt"
	"os"
	"time"

	"github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
	storagev1 "k8s.io/api/storage/v1"
	"k8s.io/apimachinery/pkg/labels"

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

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

const (
	NodeGroupCreated = "CreateCdcNodeGroup"
	NodeGroupDeleted = "DeleteCdcNodeGroup"
)

var errUnimplemented = fmt.Errorf("provider unimplemented")

var _ Provider = &Unimplemented{}

func NewUnimplemented() *Unimplemented {
	return &Unimplemented{}
}

type Unimplemented struct {
}

func (p *Unimplemented) BuildBackup(backup *cloudv1.Backup, cluster *cloudv1.Cluster) (*v1alpha1.Backup, error) {
	return nil, errUnimplemented
}

func (p *Unimplemented) CreateBRNode(
	ctx context.Context,
	network *cloudv1.Network,
	ngSpec *cloudv1.NodegroupSpec) error {
	return errUnimplemented
}

func (p *Unimplemented) DeleteBRNode(
	ctx context.Context,
	network *cloudv1.Network,
	ngSpecName string) error {
	return errUnimplemented
}

func (p *Unimplemented) GetBackupClient(ctx context.Context, cluster *cloudv1.Backup) (client.Client, error) {
	return nil, errUnimplemented
}

func (p *Unimplemented) GetBackupNamespace(context.Context, *cloudv1.Backup) (string, error) {
	return "", errUnimplemented
}

func (p *Unimplemented) BuildRestore(restore *cloudv1.Restore, cluster *cloudv1.Cluster) (*v1alpha1.Restore, error) {
	return nil, errUnimplemented
}

func (p *Unimplemented) PostRestoreFinished(ctx context.Context, restore *cloudv1.Restore) error {
	return nil
}

func (p *Unimplemented) GetClient(ctx context.Context, cluster *cloudv1.Cluster) (client.Client, error) {
	return nil, errUnimplemented
}

func (p *Unimplemented) GetKubernetesStatus(cluster *cloudv1.Cluster) (*cloudv1.KubernetesStatus, error) {
	return nil, errUnimplemented
}

func (p *Unimplemented) GetComponentNodeLabels(componentType cloudv1.ComponentType) map[string]string {
	return map[string]string{}
}

func (p *Unimplemented) GetComponentPodLabels(componentType cloudv1.ComponentType) map[string]string {
	return map[string]string{}
}

func (p *Unimplemented) GetNodeZoneFromLabels(_ map[string]string) string {
	return ""
}

func (p *Unimplemented) GetNodeInstanceTypeFromLabels(_ map[string]string) string {
	return ""
}

func (p *Unimplemented) Overlay(*v1alpha1.TidbCluster) error {
	return errUnimplemented
}

func (p *Unimplemented) GetCdcUpstreamClient(context.Context, *cloudv1.TiCDC) (client.Client, error) {
	return nil, errUnimplemented
}

func (p *Unimplemented) GetCdcClient(context.Context, *cloudv1.Network) (client.Client, error) {
	return nil, errUnimplemented
}

func (p *Unimplemented) GetCdcKubernetesStatus(*cloudv1.Cluster) (*cloudv1.KubernetesStatus, error) {
	return nil, errUnimplemented
}

func (p *Unimplemented) CreateCdcNodeGroup(ctx context.Context, network *cloudv1.TiCDC, cls *cloudv1.Cluster, ngs *nodegroup.Set) (map[string]string, error) {
	// do nothing
	if utils.InIntegrationTest() {
		os.Setenv("CreateCdcNodeGroup", "true")
	}
	return map[string]string{}, nil
}

func (p *Unimplemented) DeleteCdcNodeGroup(ctx context.Context, network *cloudv1.TiCDC, ngs *nodegroup.Set) error {
	// do nothing
	if utils.InIntegrationTest() {
		os.Setenv("DeleteCdcNodeGroup", "true")
	}
	return nil
}

func (p *Unimplemented) ReleaseNodes(ctx context.Context, cr *cloudv1.TiCDC, ngNamePrefix string, labelSet labels.Set) error {
	return nil
}

func (p *Unimplemented) UpdateNodegroupTopology(ctx context.Context, cr *cloudv1.TiCDC, topology map[string]int) error {
	return nil
}

func (p *Unimplemented) SetResourceLabels(ctx context.Context, cr *cloudv1.TiCDC) error {
	return nil
}

func (p *Unimplemented) EnsureAllNodegroupsReady(ctx context.Context, cr *cloudv1.TiCDC) error {
	return nil
}

func (p *Unimplemented) GetNodegroupsByFilter(ctx context.Context, cr *cloudv1.TiCDC, selector labels.Selector) (map[string]int, error) {
	return nil, nil
}

func (p *Unimplemented) DeleteNodegroupsByFilter(ctx context.Context, cr *cloudv1.TiCDC, selector labels.Selector) error {
	return nil
}

func (p *Unimplemented) RequireV1CertManager() bool {
	return false
}

func (c *Unimplemented) Credentials(ctx context.Context, network *cloudv1.Network) ([]byte, error) {
	return nil, nil
}

func (p *Unimplemented) CertificateOptions(cluster *cloudv1.Cluster) (kind string, name string, group string, d time.Duration) {
	return consts.AwsPcaIssuerKind, consts.AwsPcaIssuer, consts.CertManagerGroup, consts.CertificateDuration
}

func (p *Unimplemented) OverrideImage(cluster *cloudv1.Cluster, imageName string) string {
	return imageName
}

func (p *Unimplemented) GetNetworkProxyBaseURL(_ context.Context, network *cloudv1.Network) (string, error) {
	return "", errUnimplemented
}

func (p *Unimplemented) IsDPCompatMode() bool {
	return false
}

func (p *Unimplemented) BuildStorageClass() *storagev1.StorageClass {
	return nil
}
