package zddc

import (
	"os"
	"path/filepath"
	"strings"
	"testing"
)

// TestEmbeddedDefaultsParse — the shipped defaults.zddc.yaml must
// parse cleanly into a ZddcFile. Regression guard against accidental
// YAML syntax errors in the source-of-truth file.
func TestEmbeddedDefaultsParse(t *testing.T) {
	zf, err := EmbeddedDefaults()
	if err != nil {
		t.Fatalf("EmbeddedDefaults: %v", err)
	}
	if zf.Title == "" {
		t.Errorf("embedded defaults have no title")
	}
}

// TestEmbeddedDefaultsBytesDumpable — the bytes used by the show-
// defaults CLI must be non-empty and start with a comment so an
// operator pasting them into a real file sees the header.
func TestEmbeddedDefaultsBytesDumpable(t *testing.T) {
	got := EmbeddedDefaultsBytes()
	if len(got) == 0 {
		t.Fatal("EmbeddedDefaultsBytes returned empty slice")
	}
	if !strings.HasPrefix(strings.TrimLeft(string(got), " \t"), "#") {
		t.Errorf("expected leading comment, got: %q", string(got[:60]))
	}
}

// TestCascadeIncludesEmbeddedByDefault — a fresh deployment with no
// on-disk .zddc still gets the embedded defaults reachable via
// chain.Embedded.
func TestCascadeIncludesEmbeddedByDefault(t *testing.T) {
	resetCache()
	root := t.TempDir()
	leaf := filepath.Join(root, "Proj")
	if err := mkdirAll(leaf); err != nil {
		t.Fatal(err)
	}
	chain, err := EffectivePolicy(root, leaf)
	if err != nil {
		t.Fatal(err)
	}
	if chain.Embedded.Title == "" {
		t.Errorf("chain.Embedded.Title empty, want defaults title to populate")
	}
}

// TestCascadeInheritFalseDropsEmbedded — when an on-disk .zddc sets
// top-level `inherit: false`, the embedded layer is zeroed out.
func TestCascadeInheritFalseDropsEmbedded(t *testing.T) {
	resetCache()
	root := t.TempDir()
	writeZddc(t, root, "title: 'op-managed'\ninherit: false\n")
	leaf := filepath.Join(root, "Proj")
	if err := mkdirAll(leaf); err != nil {
		t.Fatal(err)
	}
	chain, err := EffectivePolicy(root, leaf)
	if err != nil {
		t.Fatal(err)
	}
	if chain.Embedded.Title != "" {
		t.Errorf("chain.Embedded.Title = %q, want empty (inherit:false should drop embedded)",
			chain.Embedded.Title)
	}
	// On-disk level still present.
	if got := chain.Levels[0].Title; got != "op-managed" {
		t.Errorf("Levels[0].Title = %q, want %q", got, "op-managed")
	}
}

// TestCascadeInheritTrueExplicitKeepsEmbedded — `inherit: true`
// explicitly is the same as omitting it (default behaviour).
func TestCascadeInheritTrueExplicitKeepsEmbedded(t *testing.T) {
	resetCache()
	root := t.TempDir()
	writeZddc(t, root, "title: 'op-managed'\ninherit: true\n")
	leaf := filepath.Join(root, "Proj")
	if err := mkdirAll(leaf); err != nil {
		t.Fatal(err)
	}
	chain, err := EffectivePolicy(root, leaf)
	if err != nil {
		t.Fatal(err)
	}
	if chain.Embedded.Title == "" {
		t.Errorf("chain.Embedded.Title empty, want defaults to remain since inherit: true is the default")
	}
}

func mkdirAll(p string) error {
	return os.MkdirAll(p, 0o755)
}
