//go:build linux

package stacks

import (
	"io"
	"log"
	"os"
	"path/filepath"
	"testing"

	"gitea.dooplex.hu/admin/felhom-controller/internal/appbackup"
)

// TestWalkMerge_PreservesSetgid is the #8 fix proof: the non-app merge walk must preserve the SOURCE
// dir's setgid bit + group, so the userdata ownership convention (2775 setgid, gid 1000) survives a
// whole-drive migration. Companion: the pre-fix path (MkdirAll 0755 / copyFile .Perm()) drops setgid
// → this test FAILS on the old code (mutation-proven separately).
func TestWalkMerge_PreservesSetgid(t *testing.T) {
	lg := log.New(io.Discard, "", 0)
	src := t.TempDir()
	dst := t.TempDir()

	// Source userdata-style tree with setgid dirs (the convention).
	media := filepath.Join(src, "userdata", "media")
	if err := os.MkdirAll(media, 0o755); err != nil {
		t.Fatal(err)
	}
	for _, d := range []string{filepath.Join(src, "userdata"), media} {
		if err := os.Chmod(d, os.ModeSetgid|0o775); err != nil {
			t.Fatal(err)
		}
	}
	if err := os.WriteFile(filepath.Join(media, "movie.txt"), []byte("VID"), 0o664); err != nil {
		t.Fatal(err)
	}

	if err := walkMerge(lg, src, dst, nil, false, nil); err != nil {
		t.Fatalf("walkMerge: %v", err)
	}

	// Target media dir must still carry setgid + the source group.
	srcFI, _ := os.Stat(media)
	dstFI, err := os.Stat(filepath.Join(dst, "userdata", "media"))
	if err != nil {
		t.Fatalf("target media dir missing: %v", err)
	}
	if dstFI.Mode()&os.ModeSetgid == 0 {
		t.Errorf("migration DROPPED the setgid bit on the dir: mode=%v", dstFI.Mode())
	}
	if dstFI.Mode().Perm() != 0o775 {
		t.Errorf("target dir perm = %o, want 0775", dstFI.Mode().Perm())
	}
	sg, _ := appbackup.StatGID(srcFI)
	dg, _ := appbackup.StatGID(dstFI)
	if sg != dg {
		t.Errorf("target dir group = %d, want source group %d", dg, sg)
	}
}
