package packs

import (
	"context"
	"strings"
)

type peerDeclarationOverridesContextKey struct{}

// WithPeerDeclarationOverrides carries reconcile-scoped current-source
// declaration truth for active drifted peers. Outside reconcile, callers should
// omit overrides so installed-row helper reads remain strict.
func WithPeerDeclarationOverrides(ctx context.Context, overrides map[string]*SourceBackedPack) context.Context {
	if len(overrides) == 0 {
		return ctx
	}
	normalized := normalizePeerDeclarationOverrides(overrides)
	if len(normalized) == 0 {
		return ctx
	}
	return context.WithValue(ctx, peerDeclarationOverridesContextKey{}, normalized)
}

// WithExactPeerDeclarationOverrides replaces any inherited override snapshot.
// Unlike WithPeerDeclarationOverrides, an empty map deliberately masks an
// outer snapshot so callers can express that no peers are runtime-effective.
func WithExactPeerDeclarationOverrides(ctx context.Context, overrides map[string]*SourceBackedPack) context.Context {
	normalized := normalizePeerDeclarationOverrides(overrides)
	return context.WithValue(ctx, peerDeclarationOverridesContextKey{}, normalized)
}

func normalizePeerDeclarationOverrides(overrides map[string]*SourceBackedPack) map[string]*SourceBackedPack {
	normalized := make(map[string]*SourceBackedPack, len(overrides))
	for name, pack := range overrides {
		if pack == nil {
			continue
		}
		key := strings.ToLower(strings.TrimSpace(name))
		if key == "" {
			key = strings.ToLower(strings.TrimSpace(pack.Name()))
		}
		if key == "" {
			continue
		}
		normalized[key] = pack
	}
	return normalized
}

func PeerDeclarationOverrideFromContext(ctx context.Context, packName string) (*SourceBackedPack, bool) {
	if ctx == nil {
		return nil, false
	}
	overrides, _ := ctx.Value(peerDeclarationOverridesContextKey{}).(map[string]*SourceBackedPack)
	if len(overrides) == 0 {
		return nil, false
	}
	pack, ok := overrides[strings.ToLower(strings.TrimSpace(packName))]
	if !ok || pack == nil {
		return nil, false
	}
	return pack, true
}
