// Package metrics is a tiny in-process registry of named counters and gauges
// exposed as JSON at /metricsz. No external metrics system is required.
package metrics

import (
	"sync"
	"sync/atomic"
)

type Registry struct {
	mu       sync.RWMutex
	counters map[string]*atomic.Int64
	gauges   map[string]*atomic.Int64
}

func NewRegistry() *Registry {
	return &Registry{
		counters: make(map[string]*atomic.Int64),
		gauges:   make(map[string]*atomic.Int64),
	}
}

func (r *Registry) cell(m map[string]*atomic.Int64, name string) *atomic.Int64 {
	r.mu.RLock()
	c, ok := m[name]
	r.mu.RUnlock()
	if ok {
		return c
	}
	r.mu.Lock()
	defer r.mu.Unlock()
	if c, ok = m[name]; !ok {
		c = new(atomic.Int64)
		m[name] = c
	}
	return c
}

// Inc adds delta to a monotonic counter.
func (r *Registry) Inc(name string, delta int64) { r.cell(r.counters, name).Add(delta) }

// Set assigns the current value of a gauge (e.g. queue depth).
func (r *Registry) Set(name string, value int64) { r.cell(r.gauges, name).Store(value) }

// Snapshot returns a point-in-time copy of all values for /metricsz.
func (r *Registry) Snapshot() (counters, gauges map[string]int64) {
	r.mu.RLock()
	defer r.mu.RUnlock()
	counters = make(map[string]int64, len(r.counters))
	for k, v := range r.counters {
		counters[k] = v.Load()
	}
	gauges = make(map[string]int64, len(r.gauges))
	for k, v := range r.gauges {
		gauges[k] = v.Load()
	}
	return counters, gauges
}
