package agent

import (
	"sync"

	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/sets"
)

// imagePullSecretTracker tracks the image pull secret and the downstream namespaces where it is to be synced
type imagePullSecretTracker struct {
	mu    sync.Mutex
	store map[types.NamespacedName]sets.Set[string]
}

func newImagePullSecretTracker() *imagePullSecretTracker {
	return &imagePullSecretTracker{store: make(map[types.NamespacedName]sets.Set[string])}
}

// get returns all the workspace namespaces that have the passed secret cloned.
func (i *imagePullSecretTracker) get(secretNamespace, secretName string) []string {
	i.mu.Lock()
	defer i.mu.Unlock()
	key := types.NamespacedName{Name: secretName, Namespace: secretNamespace}
	namespacesWithClonedSecrets, exists := i.store[key]
	if !exists {
		return nil
	}

	return namespacesWithClonedSecrets.UnsortedList()
}

// set registers that the workspace namespace contains the passed secret cloned.
func (i *imagePullSecretTracker) set(secretNamespace, secretName, workspaceNamespace string) {
	i.mu.Lock()
	defer i.mu.Unlock()
	key := types.NamespacedName{Name: secretName, Namespace: secretNamespace}
	namespacesWithClonedSecrets, exists := i.store[key]
	if !exists {
		namespacesWithClonedSecrets = make(sets.Set[string])
		i.store[key] = namespacesWithClonedSecrets
	}
	namespacesWithClonedSecrets.Insert(workspaceNamespace)
}

// delete unregisters the workspace namespace as having the passed secret cloned.
func (i *imagePullSecretTracker) delete(secretNamespace, secretName, workspaceNamespace string) {
	i.mu.Lock()
	defer i.mu.Unlock()
	key := types.NamespacedName{Name: secretName, Namespace: secretNamespace}
	namespacesWithClonedSecrets, exists := i.store[key]
	if !exists {
		return
	}

	namespacesWithClonedSecrets = namespacesWithClonedSecrets.Delete(workspaceNamespace)
	if namespacesWithClonedSecrets.Len() == 0 {
		delete(i.store, key)
	}

}
