package main

import (
	"context"
	"fmt"
	"os"
	"time"

	v1alpha1 "github.com/pfeifferj/container-mom-go/pkg/apis/containermom/v1alpha1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/config"
)

var scheme = runtime.NewScheme()

func init() {
	fmt.Println("Initializing scheme...")
	_ = clientgoscheme.AddToScheme(scheme)
	_ = v1alpha1.AddToScheme(scheme)
	fmt.Println("Scheme initialized")
}

func main() {
	// Use context with timeout for safety
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	// Set up logging
	ctrl.SetLogger(ctrl.Log.WithName("test-wlc"))

	fmt.Println("=== Starting test program ===")

	// Get config from kubeconfig
	fmt.Println("Getting Kubernetes config...")
	cfg, err := config.GetConfig()
	if err != nil {
		fmt.Printf("ERROR: Failed to get Kubernetes config: %v\n", err)
		os.Exit(1)
	}
	fmt.Println("Kubernetes config obtained successfully")

	// Create a client
	fmt.Println("Creating Kubernetes client...")
	k8sClient, err := client.New(cfg, client.Options{Scheme: scheme})
	if err != nil {
		fmt.Printf("ERROR: Failed to create client: %v\n", err)
		os.Exit(1)
	}
	fmt.Println("Kubernetes client created successfully")

	// Get the CR
	fmt.Println("Attempting to get ContainerMomDeployment CR 'josie-lol'...")
	cr := &v1alpha1.ContainerMomDeployment{}
	err = k8sClient.Get(ctx, client.ObjectKey{Name: "josie-lol", Namespace: "container-mom-system"}, cr)
	if err != nil {
		fmt.Printf("ERROR: Failed to get CR: %v\n", err)
		// List all CRs to see what's available
		crList := &v1alpha1.ContainerMomDeploymentList{}
		if listErr := k8sClient.List(ctx, crList); listErr != nil {
			fmt.Printf("ERROR: Failed to list CRs: %v\n", listErr)
		} else {
			fmt.Println("Available ContainerMomDeployments:")
			for _, item := range crList.Items {
				fmt.Printf("  - %s in namespace %s\n", item.Name, item.Namespace)
			}
		}
		os.Exit(1)
	}

	fmt.Printf("Found CR: %s with clusters: %v\n", cr.Name, cr.Spec.Clusters)

	// Generate a namespace name
	nsName := fmt.Sprintf("wkl-%s-%s", cr.Name, "test123")

	fmt.Printf("Creating namespace for ContainerMomDeployment: %s, namespace: %s\n", cr.Name, nsName)

	// Create the namespace
	ns := &corev1.Namespace{
		ObjectMeta: metav1.ObjectMeta{
			Name: nsName,
			Labels: map[string]string{
				"app.kubernetes.io/managed-by": "container-mom-test",
				"containermom.mom/deployment":  cr.Name,
			},
		},
	}

	// Try to create the namespace
	fmt.Println("Attempting to create namespace...")
	err = k8sClient.Create(ctx, ns)
	if err != nil {
		if errors.IsAlreadyExists(err) {
			fmt.Printf("Namespace %s already exists\n", nsName)
		} else {
			fmt.Printf("ERROR: Failed to create namespace: %v\n", err)
			os.Exit(1)
		}
	} else {
		fmt.Printf("Created namespace %s successfully\n", nsName)
	}

	// Add annotation to CR to persist namespace
	fmt.Println("Updating CR with namespace annotation...")
	if cr.Annotations == nil {
		cr.Annotations = make(map[string]string)
	}
	cr.Annotations["containermom.mom/namespace"] = nsName

	if err := k8sClient.Update(ctx, cr); err != nil {
		fmt.Printf("ERROR: Failed to update CR with namespace annotation: %v\n", err)
	} else {
		fmt.Println("Updated CR with namespace annotation successfully")
	}

	// Check if we can read the updated CR with the annotation
	fmt.Println("Reading back the updated CR...")
	updatedCR := &v1alpha1.ContainerMomDeployment{}
	if err := k8sClient.Get(ctx, client.ObjectKey{Name: cr.Name, Namespace: cr.Namespace}, updatedCR); err != nil {
		fmt.Printf("ERROR: Failed to read updated CR: %v\n", err)
	} else {
		fmt.Printf("Read updated CR: %s with namespace annotation: %s\n",
			updatedCR.Name,
			updatedCR.Annotations["containermom.mom/namespace"])
	}

	fmt.Println("=== Test completed! ===")
}
