package gke

import (
	"context"

	corev1 "k8s.io/api/core/v1"
	storagev1 "k8s.io/api/storage/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/utils/pointer"
	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

	"github.com/tidbcloud/eks-provider/controllers/network/task"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/pkg/consts"
	"github.com/tidbcloud/infra-provider/pkg/deploy"
	"github.com/tidbcloud/infra-provider/pkg/k8s"
)

type StorageClass struct {
	*task.BaseTask
}

const (
	defaultProvisioner = "pd.csi.storage.gke.io"
)

var (
	bindingMode   = storagev1.VolumeBindingWaitForFirstConsumer
	reclaimPolicy = corev1.PersistentVolumeReclaimDelete
)

func storageclass(sc cloudv1.StorageClass) *storagev1.StorageClass {
	return &storagev1.StorageClass{
		ObjectMeta: metav1.ObjectMeta{
			Name: sc.Name,
		},
		VolumeBindingMode:    &bindingMode,
		AllowVolumeExpansion: pointer.Bool(true),
		ReclaimPolicy:        &reclaimPolicy,
		Provisioner:          defaultProvisioner,
		Parameters: map[string]string{
			"csi.storage.k8s.io/fstype": "ext4",
			"type":                      sc.Type,
			// "labels":                    fmt.Sprintf("%s=%s", consts.TagKeyCrossplaneVendor, consts.TagValCrossplaneVendor),
		},
		MountOptions: []string{"nodelalloc,noatime"},
	}
}

func NewStorageClass(ctx *task.Context) *StorageClass {
	return &StorageClass{BaseTask: &task.BaseTask{Context: ctx}}
}

func (t *StorageClass) Name() string {
	return "StorageClass"
}

func (t *StorageClass) Create(ctx context.Context) deploy.Result {
	var classes = []*storagev1.StorageClass{
		// Infra API defaults an empty storage class to cloud-ssd, and the provider spec
		// will not include the cloud-ssd storage class.
		{
			ObjectMeta: metav1.ObjectMeta{
				Name: "cloud-ssd",
			},
			VolumeBindingMode:    &bindingMode,
			AllowVolumeExpansion: pointer.Bool(true),
			ReclaimPolicy:        &reclaimPolicy,
			Provisioner:          defaultProvisioner,
			Parameters: map[string]string{
				"csi.storage.k8s.io/fstype": "ext4",
				"type":                      consts.GCPVolumeTypePDBalanced,
				// "labels":                    fmt.Sprintf("%s=%s", consts.TagKeyCrossplaneVendor, consts.TagValCrossplaneVendor),
			},
		},
	}
	storageClasses := []cloudv1.StorageClass{
		{
			Name: k8s.ImportGp3StorageClassName,
			Type: consts.GCPVolumeTypePDBalanced,
		},
		{
			Name: consts.MetricsAgentStorageClassName,
			Type: consts.GCPVolumeTypePDSSD,
		},
		{
			Name: k8s.TiCDCGp3StorageClassName,
			Type: consts.GCPVolumeTypePDBalanced,
		},
	}
	for _, sc := range storageClasses {
		classes = append(classes, storageclass(sc))
	}

	cli, err := t.Remote.GetClient(ctx)
	if err != nil {
		return deploy.Panic(err)
	}
	for _, storageClass := range classes {
		_, err := controllerutil.CreateOrUpdate(ctx, cli, storageClass, func() error { return nil })
		if err != nil {
			return deploy.Error(err)
		}
	}
	return deploy.Done()
}
