package xds

// Source computes the DESIRED snapshot for a node from a source of truth
// (Kubernetes objects in gw-10, or a service registry).
type Source interface {
	Desired(node string) *Snapshot
}

// Reconciler is a level-triggered loop: it derives the desired snapshot,
// versions it by content hash, and pushes only when it changed (debounce)
// and is consistent. A no-op desired state is a no-op reconcile; an
// inconsistent one keeps the last good snapshot in force.
type Reconciler struct {
	Cache  *SnapshotCache
	Source Source
	Node   string

	last string // last fingerprint pushed
}

// ReconcileOnce computes desired state and converges the cache toward it.
// Returns whether it pushed a new version and any consistency error.
func (r *Reconciler) ReconcileOnce() (pushed bool, err error) {
	s := r.Source.Desired(r.Node)
	fp := s.Fingerprint()
	if fp == r.last {
		return false, nil // identical desired state -> debounce, no push
	}
	s.Version = fp
	if err := r.Cache.SetSnapshot(r.Node, s); err != nil {
		return false, err // inconsistent: keep last-known-good, surface error
	}
	r.last = fp
	return true, nil
}
