package localapi

import (
	"context"
	"io"
	"os"
	"regexp"
	"testing"
)

// stagingRecorderRunner is a fake proxmox.Runner recording every call vector and snapshotting each
// install SOURCE file's content at call time (the deferred os.Remove erases it afterwards).
type stagingRecorderRunner struct {
	calls      [][]string
	srcContent map[string]string // install dest → staged source content
}

func (r *stagingRecorderRunner) Run(_ context.Context, name string, args ...string) ([]byte, []byte, error) {
	r.calls = append(r.calls, append([]string{name}, args...))
	if name == "install" && len(args) >= 2 {
		src, dest := args[len(args)-2], args[len(args)-1]
		if r.srcContent == nil {
			r.srcContent = map[string]string{}
		}
		b, _ := os.ReadFile(src)
		r.srcContent[dest] = string(b)
	}
	return nil, nil, nil
}

func (r *stagingRecorderRunner) RunStdin(ctx context.Context, _ io.Reader, name string, args ...string) ([]byte, []byte, error) {
	return r.Run(ctx, name, args...)
}

// installSources returns the install-call source paths keyed by destination.
func (r *stagingRecorderRunner) installSources() map[string][]string {
	out := map[string][]string{}
	for _, c := range r.calls {
		if c[0] == "install" && len(c) >= 3 {
			src, dest := c[len(c)-2], c[len(c)-1]
			out[dest] = append(out[dest], src)
		}
	}
	return out
}

// TestInstallSharedParent_RandomTempName is the audit-B1 negative test for the shared-parent boot
// persistence install: both staged install SOURCES (script + unit) must be RANDOM os.CreateTemp names
// (felhom-shared-parent-<random>.sh / .service), never the fixed, pre-creatable /tmp names (a local
// TOCTOU into a root-executed boot script), and two consecutive installs must use DIFFERENT paths.
func TestInstallSharedParent_RandomTempName(t *testing.T) {
	r := &stagingRecorderRunner{}
	b := NewGuestBinder(r, nil)
	if err := b.installSharedParentUnit(context.Background()); err != nil {
		t.Fatalf("installSharedParentUnit #1: %v", err)
	}
	if err := b.installSharedParentUnit(context.Background()); err != nil {
		t.Fatalf("installSharedParentUnit #2: %v", err)
	}

	srcs := r.installSources()
	cases := []struct {
		dest    string
		random  *regexp.Regexp
		fixed   *regexp.Regexp
		content string
	}{
		{sharedParentScriptPath, regexp.MustCompile(`felhom-shared-parent-[^/\\]+\.sh$`),
			regexp.MustCompile(`felhom-shared-parent\.sh$`), sharedParentScript},
		{sharedParentUnitPath, regexp.MustCompile(`felhom-shared-parent-[^/\\]+\.service$`),
			regexp.MustCompile(`felhom-shared-parent\.service$`), sharedParentUnit},
	}
	for _, tc := range cases {
		got := srcs[tc.dest]
		if len(got) != 2 {
			t.Fatalf("dest %s: expected 2 install calls, got %d (%v)", tc.dest, len(got), got)
		}
		for i, src := range got {
			if !tc.random.MatchString(src) {
				t.Errorf("dest %s call %d: source %q does not match the random temp pattern", tc.dest, i, src)
			}
			if tc.fixed.MatchString(src) {
				t.Errorf("dest %s call %d: source %q is the FIXED predictable temp name (B1 TOCTOU)", tc.dest, i, src)
			}
			if _, err := os.Stat(src); err == nil {
				t.Errorf("dest %s: staged temp %q left behind (defer os.Remove missing)", tc.dest, src)
			}
		}
		if got[0] == got[1] {
			t.Errorf("dest %s: two consecutive installs staged through the SAME source %q — must be random per call", tc.dest, got[0])
		}
		// Non-hollow: the staged file carried the real content at install time.
		if r.srcContent[tc.dest] != tc.content {
			t.Errorf("dest %s: staged content mismatch (got %d bytes, want %d)", tc.dest, len(r.srcContent[tc.dest]), len(tc.content))
		}
	}
}
