package policy

import (
	"context"
	"testing"

	"codeberg.org/VARASYS/ZDDC/zddc/internal/zddc"

	"github.com/open-policy-agent/opa/rego"
)

// TestReferenceRego_FailClosedOnWrites pins the security contract of the
// bundled reference Rego skeleton: it models READ-ACL only, so any non-read
// action must be DENIED even when the read-ACL would grant — and the only
// write-capable principal is an elevated admin. This is the behavior that,
// untested, previously let a verb-blind policy ship claiming to "mirror the
// internal decider exactly." See rego/access.rego.
func TestReferenceRego_FailClosedOnWrites(t *testing.T) {
	ctx := context.Background()

	stdQ, err := rego.New(
		rego.Query("data.zddc.access.allow"),
		rego.Module("access.rego", ReferenceRego),
	).PrepareForEval(ctx)
	if err != nil {
		t.Fatalf("compile access.rego: %v", err)
	}

	// A chain that GRANTS full rwcd to alice — so any denial below is the
	// action gate, not a missing ACL.
	grant := zddc.PolicyChain{
		Levels:     []zddc.ZddcFile{{ACL: zddc.ACLRules{Permissions: map[string]string{"*@example.com": "rwcd"}}}},
		HasAnyFile: true,
	}

	evalAllow := func(q rego.PreparedEvalQuery, action string, admin bool) bool {
		in := AllowInput{Path: "/p/", Action: action, PolicyChain: chainToSerializable(grant)}
		in.User.Email = "alice@example.com"
		in.User.IsActiveAdmin = admin
		regoInput, err := canonicalInput(in)
		if err != nil {
			t.Fatalf("encode: %v", err)
		}
		rs, err := q.Eval(ctx, rego.EvalInput(regoInput))
		if err != nil {
			t.Fatalf("eval: %v", err)
		}
		if len(rs) == 0 {
			t.Fatalf("no result")
		}
		v, ok := rs[0].Expressions[0].Value.(bool)
		if !ok {
			t.Fatalf("result not bool: %v", rs[0].Expressions[0].Value)
		}
		return v
	}

	cases := []struct {
		name      string
		q         rego.PreparedEvalQuery
		action    string
		admin     bool
		wantAllow bool
	}{
		// Commercial: reads granted, every write verb denied (fail-closed).
		{"access read allowed", stdQ, ActionRead, false, true},
		{"access empty-action(read) allowed", stdQ, "", false, true},
		{"access write denied", stdQ, ActionWrite, false, false},
		{"access create denied", stdQ, ActionCreate, false, false},
		{"access delete denied", stdQ, ActionDelete, false, false},
		{"access admin-action denied", stdQ, ActionAdmin, false, false},
		// An elevated admin is the one write-capable principal.
		{"access write allowed for active admin", stdQ, ActionWrite, true, true},
		{"access delete allowed for active admin", stdQ, ActionDelete, true, true},
	}
	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			if got := evalAllow(tc.q, tc.action, tc.admin); got != tc.wantAllow {
				t.Errorf("allow=%v, want %v (action=%q active_admin=%v)", got, tc.wantAllow, tc.action, tc.admin)
			}
		})
	}
}
