package eks

import (
	"context"

	storagev1 "k8s.io/api/storage/v1"
	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

	"github.com/tidbcloud/eks-provider/controllers"
	"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"
)

type StorageClass struct {
	*task.BaseTask
}

func storageclass(sc cloudv1.StorageClass) *storagev1.StorageClass {
	return controllers.ConvertAWSStorageClass(sc)
}

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{}
	storageClasses := []cloudv1.StorageClass{
		{
			// Infra API defaults an empty storage class to cloud-ssd, and the provider spec
			// will not include the cloud-ssd storage class.
			// Currently the db-monitor will use this storageclass
			Name:       "cloud-ssd",
			Type:       consts.AWSVolumeTypeGP3,
			IOPS:       consts.MetricsAgentGp3IOPS,
			Throughput: consts.MetricsAgentGp3ThroughputMBps,
		},
		{
			Name:       consts.ImportGp3StorageClassName,
			Type:       consts.AWSVolumeTypeGP3,
			IOPS:       consts.ImportGp3IOPS,
			Throughput: consts.ImportGp3ThroughputMBps,
		},
		{
			Name:       consts.MetricsAgentStorageClassName,
			Type:       consts.AWSVolumeTypeGP3,
			IOPS:       consts.MetricsAgentGp3IOPS,
			Throughput: consts.MetricsAgentGp3ThroughputMBps,
		},
		{
			Name:       consts.TiCDCGp3StorageClassName,
			Type:       consts.AWSVolumeTypeGP3,
			IOPS:       consts.TiCDCGp3IOPS,
			Throughput: consts.TiCDCGp3ThroughputMBps,
		},
	}
	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()
}
