package imports

import (
	"context"

	"github.com/pingcap/errors"
	batchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	storagev1 "k8s.io/api/storage/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/rest"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"

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

// MockEnvBuilder is an mock implementation for the Env interface for testing.
type MockEnvBuilder struct {
}

// NewMockEnvBuilder creates a new MockEnvBuilder.
func NewMockEnvBuilder() *MockEnvBuilder {
	return &MockEnvBuilder{}
}

func (b *MockEnvBuilder) BuildEnvFromImport(ctx context.Context, i *cloudv1.Import) (Env, error) {
	return NewMockEnv(), nil
}

// MockEnv is an mock implementation for the Env interface for testing.
type MockEnv struct {
}

// NewMockEnv creates a new MockEnv.
func NewMockEnv() *MockEnv {
	return &MockEnv{}
}

// TCName get the tidbcluster name create by the specified cluster.
func (e *MockEnv) TCName(clusterName string) string {
	return "tidbcluster"
}

// StorageClassName used to create pv as the local storage for lighting.
func (e *MockEnv) StorageClassName() string {
	return "dummy-storage-class"
}

// PreCreateJobHook is call before we create the job.
func (e *MockEnv) PreCreateJobHook(job *batchv1.Job) error {
	return nil
}

// Credentials gets the credential file content for import.
func (e *MockEnv) Credentials(ctx context.Context) ([]byte, error) {
	return nil, nil
}

// CreateNodeGroup creates a node group in the K8S cluster.
func (e *MockEnv) CreateNodeGroup(ctx context.Context, ngs *nodegroup.Set) (map[string]string, error) {
	return nil, nil
}

// DeleteNodeGroup deletes the node group in the K8S cluster.
func (e *MockEnv) DeleteNodeGroup(ctx context.Context, ngs *nodegroup.Set) error {
	return nil
}

// GetControllerClient gets the controller runtime client for the K8S cluster.
func (e *MockEnv) GetControllerClient(ctx context.Context) (client.Client, error) {
	scheme := runtime.NewScheme()
	if err := corev1.AddToScheme(scheme); err != nil {
		return nil, errors.Annotate(err, "add core K8S objects types to scheme failed")
	}
	if err := batchv1.AddToScheme(scheme); err != nil {
		return nil, errors.Annotate(err, "add K8S batch objects types (eg. Job) to scheme failed")
	}
	dataPlaneCli := fake.NewClientBuilder().
		WithScheme(scheme).
		Build()
	return dataPlaneCli, nil
}

// GetKubeConfig gets the kubeconfig for the K8S cluster.
func (e *MockEnv) GetKubeConfig(ctx context.Context) (*rest.Config, error) {
	return nil, nil
}

// PreCreateSvcHook override svc before create.
func (e *MockEnv) PreCreateSvcHook(svc *corev1.Service) error {
	return nil
}

// PreCreateSecretHook is call before we create the secret.
func (e *MockEnv) PreCreateSecretHook(_ *corev1.Secret) error {
	return nil
}

// GetDataPlaneNamespace get the namespace for import resources in the data plane.
// It implements the Env interface.
func (e *MockEnv) GetDataPlaneNamespace() (string, error) {
	return "tidb12345", nil
}

// GetDataPlaneCertSecretName get the secret name for import resources in the data plane.
// It implements the Env interface.
func (e *MockEnv) GetClusterCertSecretName() string {
	return "tidbcluster-cluster-client-secret"
}

func (e *MockEnv) GetTiDBServerCertSecretName() string {
	return ""
}

// EnableCheckpoint returns whether enable checkpoint.
func (e *MockEnv) EnableCheckpoint() bool {
	return false
}

// BuildStorageClass builds the storage class for the K8S cluster.
func (e *MockEnv) BuildStorageClass() *storagev1.StorageClass {
	return nil
}
