package agent

import (
	"context"
	"errors"
	"log/slog"

	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/client-go/tools/cache"
)

// https://caiorcferreira.github.io/post/the-kubernetes-dynamic-client/

type k8sInformer struct {
	informer       cache.SharedIndexInformer
	lister         cache.GenericLister
	log            *slog.Logger
	backgroundTask stoppableTask
}

func newK8sInformer(log *slog.Logger, informer cache.SharedIndexInformer, lister cache.GenericLister) *k8sInformer {
	return &k8sInformer{
		informer: informer,
		lister:   lister,
		log:      log,
	}
}

func (i *k8sInformer) Start(ctx context.Context) error {
	i.backgroundTask = newStoppableTask(ctx, func(ctx context.Context) {
		i.informer.RunWithContext(ctx)
	})

	isSynced := cache.WaitForCacheSync(ctx.Done(), i.informer.HasSynced)

	if !isSynced {
		return errors.New("failed to sync informer during init")
	}

	return nil
}

func (i *k8sInformer) ListAll() []*unstructured.Unstructured {
	items := i.informer.GetIndexer().List()
	data := make([]*unstructured.Unstructured, 0, len(items))
	for _, item := range items {
		data = append(data, item.(*unstructured.Unstructured))
	}
	return data
}

func (i *k8sInformer) Get(namespace, name string) (*unstructured.Unstructured, error) {
	obj, err := i.lister.ByNamespace(namespace).Get(name)
	if err != nil {
		return nil, err
	}
	return obj.(*unstructured.Unstructured), nil
}

func (i *k8sInformer) Stop() {
	if i.backgroundTask != nil {
		i.backgroundTask.StopAndWait()
		i.log.Info("informer stopped")
	}
}
