package catalogapp

import (
	"strings"
	"testing"

	"github.com/pingcap-inc/nexuscrm-contract/pkg/appauthority"
)

func TestHandlerProjectionAuthorityRequiresExactWorkloadAdmission(t *testing.T) {
	provided := []appauthority.ProvidedCapability{
		{CapabilityID: "app.query.v1", Kind: appauthority.CapabilityKindServiceHandler,
			HandlerRef: "query", RequiredRuntimeCapabilities: []string{"runtime.query.v1"}},
		{CapabilityID: "app.session.v1", Kind: appauthority.CapabilityKindServiceHandler,
			HandlerRef: "session", RequiredRuntimeCapabilities: []string{"runtime.query.v1", "runtime.session.v1"}},
	}
	selected := []string{"app.query.v1"}
	admissions := []WorkloadHandlerAdmission{{
		CapabilityID: "app.session.v1", AuthorizedWorkloadID: "app-service",
		RequiredRuntimeCapabilities: []string{"runtime.query.v1", "runtime.session.v1"},
	}}
	authorized := []string{"app-service", "integration-service"}
	granted := []string{"runtime.query.v1", "runtime.session.v1"}
	gotSelected, gotAdmissions, err := canonicalHandlerProjectionAuthority(
		provided, selected, admissions, authorized, granted,
	)
	if err != nil {
		t.Fatal(err)
	}
	if len(gotSelected) != 1 || gotSelected[0] != "app.query.v1" ||
		len(gotAdmissions) != 1 || gotAdmissions[0].CapabilityID != "app.session.v1" {
		t.Fatalf("canonical authority = %#v / %#v", gotSelected, gotAdmissions)
	}

	tests := []struct {
		name       string
		selected   []string
		admissions []WorkloadHandlerAdmission
		want       string
	}{
		{name: "missing proof", selected: selected,
			want: "exactly partition"},
		{name: "unauthorized workload", selected: selected,
			admissions: []WorkloadHandlerAdmission{{CapabilityID: "app.session.v1", AuthorizedWorkloadID: "other",
				RequiredRuntimeCapabilities: []string{"runtime.query.v1", "runtime.session.v1"}}},
			want: "workload is not authorized"},
		{name: "malformed workload", selected: selected,
			admissions: []WorkloadHandlerAdmission{{CapabilityID: "app.session.v1", AuthorizedWorkloadID: "app-service\x01",
				RequiredRuntimeCapabilities: []string{"runtime.query.v1", "runtime.session.v1"}}},
			want: "workload is invalid"},
		{name: "incomplete closure", selected: selected,
			admissions: []WorkloadHandlerAdmission{{CapabilityID: "app.session.v1", AuthorizedWorkloadID: "app-service",
				RequiredRuntimeCapabilities: []string{"runtime.session.v1"}}},
			want: "complete granted Runtime dependency closure"},
		{name: "selected admission", selected: selected,
			admissions: []WorkloadHandlerAdmission{{CapabilityID: "app.query.v1", AuthorizedWorkloadID: "app-service",
				RequiredRuntimeCapabilities: []string{"runtime.query.v1"}}},
			want: "omitted verified App handler"},
		{name: "legacy proof", admissions: admissions,
			want: "legacy all-handler selection"},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			_, _, err := canonicalHandlerProjectionAuthority(
				provided, test.selected, test.admissions, authorized, granted,
			)
			if err == nil || !strings.Contains(err.Error(), test.want) {
				t.Fatalf("authority error = %v, want %q", err, test.want)
			}
		})
	}
}

// Runtime serving choices cannot be inferred from all dependencies of a
// selected composite App handler. Both handlers below share session admission.
func TestHandlerProjectionAuthorityPreservesSharedWorkloadDependency(t *testing.T) {
	provided := []appauthority.ProvidedCapability{
		{CapabilityID: "app.composite.v1", Kind: appauthority.CapabilityKindServiceHandler,
			HandlerRef: "composite", RequiredRuntimeCapabilities: []string{"runtime.query.v1", "runtime.session.v1"}},
		{CapabilityID: "app.session.v1", Kind: appauthority.CapabilityKindServiceHandler,
			HandlerRef: "session", RequiredRuntimeCapabilities: []string{"runtime.session.v1"}},
	}
	_, admissions, err := canonicalHandlerProjectionAuthority(provided, []string{"app.composite.v1"},
		[]WorkloadHandlerAdmission{{CapabilityID: "app.session.v1", AuthorizedWorkloadID: "app-service",
			RequiredRuntimeCapabilities: []string{"runtime.session.v1"}}},
		[]string{"app-service"}, []string{"runtime.query.v1", "runtime.session.v1"})
	if err != nil || len(admissions) != 1 {
		t.Fatalf("shared dependency authority = %#v, %v", admissions, err)
	}
}
