package main

import (
	"hash/fnv"
	"sync"
)

// hashString is a cheap, stable 32-bit hash (FNV-1a). Used for opaque, non-identifying
// derived ids (e.g. the prompt-cache conv id) — not for security.
func hashString(s string) uint32 {
	h := fnv.New32a()
	_, _ = h.Write([]byte(s))
	return h.Sum32()
}

// lruSet is a bounded insertion-ordered string set used for event-id dedup and
// tracking our own sent event ids. Oldest entries evict once cap is reached.
// Self-locking: events are now processed in concurrent per-message goroutines, so
// Add/Has must be safe to call from several goroutines at once.
type lruSet struct {
	mu    sync.Mutex
	cap   int
	set   map[string]struct{}
	order []string
}

func newLRUSet(cap int) *lruSet {
	return &lruSet{cap: cap, set: make(map[string]struct{}, cap), order: make([]string, 0, cap)}
}

func (l *lruSet) Has(k string) bool {
	l.mu.Lock()
	defer l.mu.Unlock()
	_, ok := l.set[k]
	return ok
}

// Add inserts k and returns true if it was newly added (false if already present).
// The check-and-insert is atomic, so two goroutines racing on the same id can
// never both get true — the in-memory dedup stays correct under concurrency.
func (l *lruSet) Add(k string) bool {
	l.mu.Lock()
	defer l.mu.Unlock()
	if _, ok := l.set[k]; ok {
		return false
	}
	if len(l.order) >= l.cap {
		oldest := l.order[0]
		l.order = l.order[1:]
		delete(l.set, oldest)
	}
	l.set[k] = struct{}{}
	l.order = append(l.order, k)
	return true
}
