package resourcemanager

import (
	"context"

	"github.com/tidbcloud/observability/pkg/common/errors"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
)

type pvcReaderWriter struct {
	kubeClient kubernetes.Interface
}

func (p pvcReaderWriter) Create(ctx context.Context, ns string, name string, req string) error {
	pvcClient := p.kubeClient.CoreV1().PersistentVolumeClaims(ns)
	request, err := resource.ParseQuantity(req)
	if err != nil {
		return WrapClientError(err)
	}
	pvc := &corev1.PersistentVolumeClaim{
		ObjectMeta: metav1.ObjectMeta{
			Name:      name,
			Namespace: ns,
		},
		Spec: corev1.PersistentVolumeClaimSpec{
			Resources: corev1.VolumeResourceRequirements{
				Requests: map[corev1.ResourceName]resource.Quantity{
					"storage": request,
				},
			},
		},
	}
	_, err = pvcClient.Create(ctx, pvc, metav1.CreateOptions{})
	return WrapClientError(err)
}

func (p pvcReaderWriter) Get(ctx context.Context, ns string, name string) (*corev1.PersistentVolumeClaim, error) {
	pvcClient := p.kubeClient.CoreV1().PersistentVolumeClaims(ns)
	pvc, err := pvcClient.Get(ctx, name, metav1.GetOptions{})
	if err != nil {
		return nil, WrapClientError(err)
	}
	if pvc == nil {
		err = errors.NewErrorf(errors.PVCNotFound, "PVC %s is not found", name)
		return nil, WrapClientError(err)
	}
	return pvc, nil
}

func (p pvcReaderWriter) Update(ctx context.Context, ns string, pvc *corev1.PersistentVolumeClaim) error {
	pvcClient := p.kubeClient.CoreV1().PersistentVolumeClaims(ns)

	_, err := pvcClient.Update(ctx, pvc, metav1.UpdateOptions{})

	return WrapClientError(err)
}

func (p pvcReaderWriter) Delete(ctx context.Context, ns string, name string) (*corev1.PersistentVolumeClaim, error) {
	pvcClient := p.kubeClient.CoreV1().PersistentVolumeClaims(ns)
	pvc, err := pvcClient.Get(ctx, name, metav1.GetOptions{})
	if err != nil {
		return nil, WrapClientError(err)
	}
	err = pvcClient.Delete(ctx, name, metav1.DeleteOptions{})

	return pvc, WrapClientError(err)
}
