package validator

import "strings"

// InMemoryWorkerLookup is a zero-deps WorkerLookup useful for tests
// and small-fixture validation. Mirrors Rust's
// `InMemoryWorkerLookup::from_records`.
//
// Lookup is case-insensitive on candidate_id since Rust's
// HashMap with PartialEq + the source data's casing inconsistency
// (some IDs uppercase, some lowercase, some mixed) means
// case-sensitive lookup misses real matches. Lower-casing on
// insert keeps the contract.
type InMemoryWorkerLookup struct {
	byID map[string]WorkerRecord
}

// NewInMemoryWorkerLookup builds a lookup from a list of records.
// Duplicate candidate_ids: last-write-wins. Empty candidate_id: skipped.
func NewInMemoryWorkerLookup(records []WorkerRecord) *InMemoryWorkerLookup {
	m := make(map[string]WorkerRecord, len(records))
	for _, r := range records {
		if r.CandidateID == "" {
			continue
		}
		m[strings.ToLower(strings.TrimSpace(r.CandidateID))] = r
	}
	return &InMemoryWorkerLookup{byID: m}
}

// Find satisfies WorkerLookup. Returns (rec, true) on hit,
// (nil, false) on miss.
func (l *InMemoryWorkerLookup) Find(candidateID string) (*WorkerRecord, bool) {
	if l == nil {
		return nil, false
	}
	r, ok := l.byID[strings.ToLower(strings.TrimSpace(candidateID))]
	if !ok {
		return nil, false
	}
	// Return a copy so callers can't mutate the lookup's internal state.
	cp := r
	return &cp, true
}

// Len exposes the size for tests + admin endpoints.
func (l *InMemoryWorkerLookup) Len() int {
	if l == nil {
		return 0
	}
	return len(l.byID)
}

// strPtr is a tiny convenience for tests that need *string fields
// on WorkerRecord.City/State/Role.
func strPtr(s string) *string { return &s }
