package runtimeapi

import (
	"context"
	"slices"
	"testing"

	"github.com/nexuscrm/metadata/catalogsnapshot"
	"github.com/nexuscrm/shared/pkg/models"
	query "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
	mutation "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordmutationv1"
)

func userCallerFixture() *ServingState {
	s := &ServingState{userAPICallers: []string{"client-a"}}
	set := &preparedServingSet{byCapability: map[string]*preparedServingState{}}
	for _, cap := range []string{query.CapabilityName, mutation.CapabilityName} {
		set.byCapability[cap] = &preparedServingState{selection: ServingSelection{OrgID: "org-a", AppInstallationID: "app-a", RuntimeCapabilityID: cap, SecurityEpoch: 7}, binding: ServingHandlerBinding{WorkloadID: "handler-a"}, view: &catalogsnapshot.RuntimeMetadataView{}}
	}
	s.prepared.Store(set)
	return s
}

func TestUserAPICallerCapabilitiesRequireMatchingPreparedAuthority(t *testing.T) {
	s := userCallerFixture()
	for _, tc := range []struct {
		name, org, app, caller string
		epoch                  uint64
		registered, allowed    bool
	}{
		{"valid", "org-a", "app-a", "client-a", 7, true, true},
		{"other-org", "org-b", "app-a", "client-a", 7, true, false},
		{"other-installation", "org-a", "app-b", "client-a", 7, true, false},
		{"stale-publication", "org-a", "app-a", "client-a", 8, true, false},
		{"missing-epoch", "org-a", "app-a", "client-a", 0, true, false},
		{"unregistered", "org-a", "app-a", "client-b", 7, false, false},
	} {
		t.Run(tc.name, func(t *testing.T) {
			caps, registered := s.UserAPICallerCapabilities(tc.org, tc.app, tc.caller, tc.epoch)
			if registered != tc.registered || (len(caps) > 0) != tc.allowed {
				t.Fatalf("registration/authority mismatch: %v %v", registered, caps)
			}
			if len(caps) > 0 && (!slices.IsSorted(caps) || len(caps) != 2) {
				t.Fatal("noncanonical capabilities")
			}
		})
	}
	s.prepared.Store(nil)
	if caps, registered := s.UserAPICallerCapabilities("org-a", "app-a", "client-a", 7); !registered || len(caps) != 0 {
		t.Fatal("missing Catalog preparation granted authority")
	}
}

func TestUserAPICallerCannotBecomeWorkloadConsumerOrHandler(t *testing.T) {
	s := userCallerFixture()
	a, _ := NewServingAdmission(s)
	trusted := TrustedCall{principalID: "user-a", user: models.UserSession{ID: "user-a"}, orgID: "org-a", appInstallationID: "app-a", callerWorkloadID: "client-a", securityEpoch: 7, capabilities: []string{query.CapabilityName}}
	// The normal SecurityAdmission owns creation of this private context.
	ctx := context.WithValue(context.Background(), trustedCallContextKey{}, trusted)
	if _, err := a.bind(ctx, query.CapabilityName); err != nil {
		t.Fatalf("registered delegated client rejected: %v", err)
	}
	trusted.callerWorkloadID = "unregistered"
	if _, err := a.bind(context.WithValue(context.Background(), trustedCallContextKey{}, trusted), query.CapabilityName); err == nil {
		t.Fatal("unregistered caller admitted")
	}
	workload := TrustedWorkloadCall{orgID: "org-a", callerWorkloadID: "client-a", capability: query.CapabilityName, securityEpoch: 7}
	if _, err := a.bind(context.WithValue(context.Background(), trustedWorkloadCallContextKey{}, workload), query.CapabilityName); err == nil {
		t.Fatal("user client became workload consumer")
	}
	if s.isUserAPICaller("client-a", "runtime.automation.execute-flow.v1") {
		t.Fatal("user client acquired an internal execution API")
	}
}
