package kubernetes

import (
	"context"
	"fmt"

	corev1 "k8s.io/api/core/v1"
	v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
	apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/rest"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

var (
	Clientset, DynamicClient = GetKubeconfig()
)

func ListCRDs() ([]string, error) {
	// Create apiextensions client
	config := ClientConfig().(*rest.Config)
	// create the clientset
	clientset, err := apiextensionsclientset.NewForConfig(config)
	if err != nil {
		return nil, fmt.Errorf("failed to create apiextensions client: %w", err)
	}
	crds, err := clientset.ApiextensionsV1().CustomResourceDefinitions().List(context.Background(), metav1.ListOptions{})
	if err != nil {
		return nil, fmt.Errorf("failed to list CRDs: %w", err)
	}
	crdNames := []string{}

	for i := range crds.Items {
		crdNames = append(crdNames, crds.Items[i].Name)
	}
	// Return CRD names
	return crdNames, nil
}

func GetManagedVMCRD() (*v1.CustomResourceDefinition, error) {
	config := ClientConfig().(*rest.Config)
	// create the clientset
	clientset, err := apiextensionsclientset.NewForConfig(config)
	if err != nil {
		return nil, err
	}
	crd, err := clientset.ApiextensionsV1().CustomResourceDefinitions().Get(context.Background(),
		"managedvirtualmachines.proxmox.alperen.cloud", metav1.GetOptions{})
	if err != nil {
		return nil, fmt.Errorf("failed to get managedVM CRD: %w", err)
	}
	return crd, nil
}

func GetSecretData(namespace string, selector *corev1.SecretKeySelector) (string, error) {
	// Get the Secret object
	secret, err := Clientset.CoreV1().Secrets(namespace).Get(context.TODO(), selector.Name, metav1.GetOptions{})
	if err != nil {
		return "", fmt.Errorf("failed to get secret %s: %w", selector.Name, err)
	}
	value, exists := secret.Data[selector.Key]
	if !exists {
		return "", fmt.Errorf("key %s not found in secret %s", selector.Key, selector.Name)
	}
	// If the optional field is set to true and the key doesn't exist, return an empty string
	if selector.Optional != nil && *selector.Optional && !exists {
		return "", nil
	}
	return string(value), nil
}

func GetReconcileMode(resource client.Object) string {
	annotations := resource.GetAnnotations()
	if annotations == nil {
		return ReconcileModeNormal
	}
	if mode, ok := annotations[ReconcileModeAnnotation]; ok {
		return mode
	}
	return ReconcileModeNormal
}
