package packs

import "testing"

func TestComponentKindRegistryBuildsConnectorRateLimitLeaf(t *testing.T) {
	contract, ok := ComponentKindContractFor(ComponentKindConnectorRateLimit)
	if !ok {
		t.Fatal("connector_rate_limit contract missing")
	}
	if contract.sourceBuildHandler == nil {
		t.Fatal("connector_rate_limit build handler missing from component-kind registry")
	}

	pack := &SourceBackedPack{
		manifest: &PackManifest{
			Name:     "test-connector",
			Category: ConnectorPack,
		},
	}
	buildCtx := &sourceBackedComponentBuildContext{
		p:                       pack,
		connectorRateLimitBatch: &connectorRateLimitPackBatch{},
	}
	component := ManifestComponent{
		Kind:          ComponentKindConnectorRateLimit,
		BusinessKey:   "test-connector/default",
		Manageability: ManageabilityLocked,
	}
	payload := []byte(`{"endpointClass":"Default","requestsPerSecond":5,"burst":10}`)

	if err := buildCtx.build(component, payload); err != nil {
		t.Fatalf("build connector_rate_limit through registry: %v", err)
	}
	if len(pack.components) != 1 {
		t.Fatalf("components len = %d, want 1", len(pack.components))
	}
	if got := pack.components[0].Kind(); got != ComponentKindConnectorRateLimit {
		t.Fatalf("component kind = %q, want %q", got, ComponentKindConnectorRateLimit)
	}
	if got := buildCtx.connectorRateLimitBatch.declaredEndpointClasses; len(got) != 1 || got[0] != "default" {
		t.Fatalf("rate-limit declared endpoints = %#v, want [default]", got)
	}
	if got := pack.runtimeStartupShallowRows; len(got) != 1 || got[0].Kind != ComponentKindConnectorRateLimit || got[0].BusinessKey != "default" {
		t.Fatalf("startup shallow rows = %#v, want connector_rate_limit default", got)
	}
}

func TestComponentKindRegistryAttachesBuildHandlersForInstallableKinds(t *testing.T) {
	contracts := DefaultComponentKindContracts()
	for kind, capability := range DefaultSourceBackedComponentCapabilityRegistry() {
		if !capability.Installable {
			continue
		}
		contract, ok := contracts[kind]
		if !ok {
			t.Fatalf("installable kind %s has no component-kind contract", kind)
		}
		if contract.sourceBuildHandler == nil {
			t.Fatalf("installable kind %s has no source-backed build handler in component-kind registry", kind)
		}
	}
}

func TestComponentKindRegistryCarriesConnectorIdentityExtractors(t *testing.T) {
	for _, tc := range []struct {
		kind ComponentKind
		raw  string
		role sourceBackedConnectorIdentityRole
		key  string
	}{
		{
			kind: ComponentKindWebhookSecret,
			raw:  `{"name":"Orders","algorithm":"HMAC-SHA256"}`,
			role: sourceBackedConnectorIdentityWebhookSecret,
			key:  "orders",
		},
		{
			kind: ComponentKindConnectorCapability,
			raw:  `{"namespace":"acme","kind":"signature_verifier","payloadHash":"abc"}`,
			role: sourceBackedConnectorIdentityCapability,
			key:  "signature_verifier",
		},
		{
			kind: ComponentKindConnectorInboundHandlerConfig,
			raw:  `{"namespace":"acme","capabilityKind":"signature_verifier","config":{"secretName":"orders"}}`,
			role: sourceBackedConnectorIdentityInboundHandlerConfig,
			key:  "signature_verifier",
		},
	} {
		contract, ok := ComponentKindContractFor(tc.kind)
		if !ok {
			t.Fatalf("%s contract missing", tc.kind)
		}
		if contract.sourceConnectorIdentity == nil {
			t.Fatalf("%s connector identity extractor missing from component-kind registry", tc.kind)
		}
		identity, ok := contract.sourceConnectorIdentity([]byte(tc.raw))
		if !ok {
			t.Fatalf("%s connector identity extractor returned false", tc.kind)
		}
		if identity.Role != tc.role {
			t.Fatalf("%s role = %q, want %q", tc.kind, identity.Role, tc.role)
		}
		gotKey := identity.CapabilityKind
		if identity.Role == sourceBackedConnectorIdentityWebhookSecret {
			gotKey = identity.WebhookSecret
		}
		if gotKey != tc.key {
			t.Fatalf("%s identity key = %q, want %q", tc.kind, gotKey, tc.key)
		}
	}
}
