package panelacl

import "testing"

func newStore(t *testing.T) *Store {
	t.Helper()
	s, err := New(t.TempDir())
	if err != nil {
		t.Fatal("New:", err)
	}
	return s
}

func TestUnmanagedPanelIsOpen(t *testing.T) {
	s := newStore(t)
	if got := s.PanelPerm("legacy", "alice", nil); got != PermWrite {
		t.Fatalf("unmanaged panel perm = %v, want write", got)
	}
}

func TestOwnerAlwaysWrites(t *testing.T) {
	s := newStore(t)
	if err := s.CreatePanel("p1", "alice"); err != nil {
		t.Fatal(err)
	}
	if got := s.PanelPerm("p1", "alice", nil); got != PermWrite {
		t.Fatalf("owner perm = %v, want write", got)
	}
	// A freshly created panel is private to its owner.
	if got := s.PanelPerm("p1", "bob", nil); got != PermNone {
		t.Fatalf("non-owner perm on private panel = %v, want none", got)
	}
}

func TestPublicAndGrants(t *testing.T) {
	s := newStore(t)
	if err := s.CreatePanel("p1", "alice"); err != nil {
		t.Fatal(err)
	}
	grants := []Grant{
		{Kind: "user", Name: "bob", Perm: "write"},
		{Kind: "group", Name: "ops", Perm: "read"},
	}
	if err := s.SetPanel("p1", "alice", "", "read", grants); err != nil {
		t.Fatal(err)
	}
	// Public read applies to anyone.
	if got := s.PanelPerm("p1", "carol", nil); got != PermRead {
		t.Fatalf("public perm = %v, want read", got)
	}
	// Direct user grant raises bob to write.
	if got := s.PanelPerm("p1", "bob", nil); got != PermWrite {
		t.Fatalf("granted user perm = %v, want write", got)
	}
	// Group membership grants read.
	if got := s.PanelPerm("p1", "dave", []string{"ops"}); got != PermRead {
		t.Fatalf("group perm = %v, want read", got)
	}
}

func TestFolderInheritance(t *testing.T) {
	s := newStore(t)
	f, err := s.CreateFolder("f1", "Shared", "", "alice")
	if err != nil {
		t.Fatal(err)
	}
	if err := s.UpdateFolder(f.ID, f.Name, "", "read", nil); err != nil {
		t.Fatal(err)
	}
	if err := s.CreatePanel("p1", "alice"); err != nil {
		t.Fatal(err)
	}
	if err := s.SetPanel("p1", "alice", f.ID, "", nil); err != nil {
		t.Fatal(err)
	}
	// The panel inherits the folder's public-read level.
	if got := s.PanelPerm("p1", "bob", nil); got != PermRead {
		t.Fatalf("inherited perm = %v, want read", got)
	}
}

func TestFolderCycleRejected(t *testing.T) {
	s := newStore(t)
	a, _ := s.CreateFolder("a", "A", "", "alice")
	b, _ := s.CreateFolder("b", "B", a.ID, "alice")
	// Re-parenting A under its own descendant B must be rejected.
	if err := s.UpdateFolder(a.ID, a.Name, b.ID, "", nil); err == nil {
		t.Fatal("expected cycle rejection, got nil")
	}
}

func TestDeleteFolderReparents(t *testing.T) {
	s := newStore(t)
	a, _ := s.CreateFolder("a", "A", "", "alice")
	b, _ := s.CreateFolder("b", "B", a.ID, "alice")
	if err := s.CreatePanel("p1", "alice"); err != nil {
		t.Fatal(err)
	}
	if err := s.SetPanel("p1", "alice", b.ID, "", nil); err != nil {
		t.Fatal(err)
	}
	if err := s.DeleteFolder(b.ID); err != nil {
		t.Fatal(err)
	}
	// B's panel should reparent to A (B's former parent), not orphan.
	if acl := s.GetPanel("p1"); acl == nil || acl.Folder != a.ID {
		t.Fatalf("panel folder after delete = %+v, want %s", acl, a.ID)
	}
}
