package jumppod

import (
	"context"
	"fmt"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"

	"github.com/tidbcloud/devops/pkg/infra/config"
	"github.com/tidbcloud/devops/pkg/infra/utils/pointer"
)

type ProviderAdapter interface {
	MutateSharedFSPV(ctx context.Context, pv *corev1.PersistentVolume) error
	MutateSharedFSPVC(ctx context.Context, pvc *corev1.PersistentVolumeClaim) error

	ServiceAccountAnnoForRole() (string, string)
}

func NewProviderAdapter(conf config.JumpServiceJumpPodConfig) (ProviderAdapter, error) {
	switch conf.Provider {
	case "eks":
		return &AdapterEKS{conf}, nil
	case "ack":
		return &AdapterACK{conf}, nil
	default:
		return nil, fmt.Errorf("unsupported provider %s", conf.Provider)
	}
}

type AdapterEKS struct {
	conf config.JumpServiceJumpPodConfig
}

func (a *AdapterEKS) MutateSharedFSPV(ctx context.Context, pv *corev1.PersistentVolume) error {
	pv.Spec.Capacity = corev1.ResourceList{
		corev1.ResourceStorage: resource.MustParse("5Gi"), // Useless, EFS size is dynamic.
	}
	pv.Spec.VolumeMode = pointer.Pointer(corev1.PersistentVolumeFilesystem)
	pv.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteMany}
	pv.Spec.MountOptions = []string{"hard", "nfsvers=4.1", "rsize=1048576", "wsize=1048576", "timeo=600", "retrans=2"}
	pv.Spec.PersistentVolumeSource = corev1.PersistentVolumeSource{
		NFS: &corev1.NFSVolumeSource{
			Path:   "/",
			Server: a.conf.JumpPodSharedFSAddr,
		},
	}
	pv.Spec.StorageClassName = fmt.Sprintf("jumppod-efs-%s", a.conf.JumpPodNamespace)

	return nil
}

func (a *AdapterEKS) MutateSharedFSPVC(ctx context.Context, pvc *corev1.PersistentVolumeClaim) error {
	pvc.Spec.Resources = corev1.ResourceRequirements{
		Requests: corev1.ResourceList{
			corev1.ResourceStorage: resource.MustParse("5Gi"), // Useless, EFS size is dynamic.
		},
	}
	pvc.Spec.VolumeMode = pointer.Pointer(corev1.PersistentVolumeFilesystem)
	pvc.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteMany}
	pvc.Spec.StorageClassName = pointer.Pointer(fmt.Sprintf("jumppod-efs-%s", a.conf.JumpPodNamespace))

	return nil
}

func (a *AdapterEKS) ServiceAccountAnnoForRole() (string, string) {
	return "eks.amazonaws.com/role-arn", a.conf.JumpPodRoleARN
}

type AdapterACK struct {
	conf config.JumpServiceJumpPodConfig
}

func (a *AdapterACK) MutateSharedFSPV(ctx context.Context, pv *corev1.PersistentVolume) error {
	pv.Spec.Capacity = corev1.ResourceList{
		corev1.ResourceStorage: resource.MustParse("5Gi"), // Useless, NAS size is dynamic.
	}
	pv.Spec.VolumeMode = pointer.Pointer(corev1.PersistentVolumeFilesystem)
	pv.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteMany}
	pv.Spec.MountOptions = []string{"vers=4", "minorversion=0", "rsize=1048576", "wsize=1048576", "hard", "timeo=600", "retrans=2", "noresvport"}
	pv.Spec.PersistentVolumeSource = corev1.PersistentVolumeSource{
		CSI: &corev1.CSIPersistentVolumeSource{
			Driver:       "nasplugin.csi.alibabacloud.com",
			VolumeHandle: pv.Name, // be same as pv name
			VolumeAttributes: map[string]string{
				"server": a.conf.JumpPodSharedFSAddr,
				"path":   "/",
			},
		},
	}
	pv.Spec.StorageClassName = fmt.Sprintf("jumppod-nas-%s", a.conf.JumpPodNamespace)
	return nil
}

func (a *AdapterACK) MutateSharedFSPVC(ctx context.Context, pvc *corev1.PersistentVolumeClaim) error {
	pvc.Spec.Resources = corev1.ResourceRequirements{
		Requests: corev1.ResourceList{
			corev1.ResourceStorage: resource.MustParse("5Gi"), // Useless, NAS size is dynamic.
		},
	}
	pvc.Spec.VolumeMode = pointer.Pointer(corev1.PersistentVolumeFilesystem)
	pvc.Spec.AccessModes = []corev1.PersistentVolumeAccessMode{corev1.ReadWriteMany}
	pvc.Spec.StorageClassName = pointer.Pointer(fmt.Sprintf("jumppod-nas-%s", a.conf.JumpPodNamespace))

	return nil
}

func (a *AdapterACK) ServiceAccountAnnoForRole() (string, string) {
	return "pod-identity.alibabacloud.com/role-name", a.conf.JumpPodRoleARN
}
