package zddc

import (
	"embed"
	"sync"
)

// defaultsBytes is the legacy single-file embedded baseline. Retained only so
// TestEmbeddedTreeMatchesYAML can prove the per-depth tree (the new source of
// truth) assembles to exactly the same ZddcFile. Removed once that guarantee
// is locked. (Still surfaced by EmbeddedDefaultsBytes / show-defaults for now.)
//
//go:embed defaults.zddc.yaml
var defaultsBytes []byte

// defaultsTreeFS is the embedded per-depth default policy tree — the source of
// truth. `all:` includes the `.zddc` (dot) files and `_any_` (underscore)
// directories that a bare //go:embed would skip.
//
//go:embed all:defaults
var defaultsTreeFS embed.FS

// EmbeddedDefaultsBytes returns the raw embedded defaults YAML. Surface: the
// show-defaults CLI dumps these to stdout.
func EmbeddedDefaultsBytes() []byte {
	out := make([]byte, len(defaultsBytes))
	copy(out, defaultsBytes)
	return out
}

var (
	embeddedTreeOnce sync.Once
	embeddedTree     PolicyTree
	embeddedTreeErr  error
)

// EmbeddedPolicyTree returns the baked-in per-depth default policy tree,
// memoised. This is the embedded form of the .zddc.zip mounted at the
// deployment root (the bottom of every cascade).
func EmbeddedPolicyTree() (PolicyTree, error) {
	embeddedTreeOnce.Do(func() {
		embeddedTree, embeddedTreeErr = LoadPolicyTreeFromFS(defaultsTreeFS, "defaults")
	})
	return embeddedTree, embeddedTreeErr
}

var (
	embeddedDefaultsOnce sync.Once
	embeddedDefaults     ZddcFile
	embeddedDefaultsErr  error
)

// EmbeddedDefaults returns the embedded defaults assembled from the per-depth
// tree into the single nested ZddcFile the cascade walker consumes, memoised.
//
// The cascade walker (EffectivePolicy) consults this as the bottom-most level
// unless an on-disk .zddc up the chain sets `inherit: false`.
func EmbeddedDefaults() (ZddcFile, error) {
	embeddedDefaultsOnce.Do(func() {
		tree, err := EmbeddedPolicyTree()
		if err != nil {
			embeddedDefaultsErr = err
			return
		}
		embeddedDefaults = tree.Assemble()
	})
	return embeddedDefaults, embeddedDefaultsErr
}
