package main

import (
	"context"
	"flag"
	"os"

	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/runtime"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	ctrl "sigs.k8s.io/controller-runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/config"
	"sigs.k8s.io/controller-runtime/pkg/log"
	"sigs.k8s.io/controller-runtime/pkg/log/zap"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
)

var (
	scheme = runtime.NewScheme()

	providerLabels = map[string]string{}
	providerType   string
)

func init() {
	log.SetLogger(zap.New())
	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
	utilruntime.Must(cloudv1.SchemeBuilder.AddToScheme(scheme))
}

type Network struct {
	cloudv1.Network
	Clusters     []string
	BackupCount  int
	PeeringCount int
	NetworkType  NetworkType
}

type NetworkType string

func main() {
	log := log.Log.WithName("network-cleanup")
	flag.StringVar(&providerType, "provider-type", "eks", "Network provider type name.")
	flag.Parse()

	// Setup a Manager
	log.Info("setting up manager")
	mgr, err := ctrl.NewManager(config.GetConfigOrDie(), ctrl.Options{
		Scheme: scheme,
	})
	if err != nil {
		log.Error(err, "unable to set up manager")
		os.Exit(1)
	}
	// Direct access apiserver
	reader := mgr.GetAPIReader()
	ctx := context.TODO()
	nls := new(cloudv1.NetworkList)

	providerLabels[cloudv1.ProviderTypeLabel] = providerType
	// List networks contains privder-type=aws
	err = reader.List(ctx, nls, &client.ListOptions{LabelSelector: labels.SelectorFromSet(providerLabels)})
	if err != nil {
		log.Error(err, "failed list network")
		os.Exit(1)
	}
	log.Info("list networks", "network counts", len(nls.Items))

	for _, n := range nls.Items {
		if n.Status.Phase == cloudv1.NetworkPhaseHibernated {
			log.Info("network is hibernated", "network name", n.Name, "network namespace", n.Namespace)
			n.Status.Phase = cloudv1.NetworkPhaseHibernating
			err = mgr.GetClient().Status().Update(ctx, &n)
			if err != nil {
				log.Error(err, "failed update network status", "network name", n.Name, "network namespace", n.Namespace)
				os.Exit(1)
			}
			log.Info("update network status to hibernating", "network name", n.Name, "network namespace", n.Namespace)
		}
	}
}
