package connector_webhooks

import (
	"net/http"
	"testing"
	"time"

	"github.com/prometheus/client_golang/prometheus/testutil"
)

func TestWebhookEndpointMetricHashIsOpaqueAndCanonical(t *testing.T) {
	first := webhookEndpointMetricHash(" Example ", "/Events")
	second := webhookEndpointMetricHash("example", "events")
	other := webhookEndpointMetricHash("example", "workflow")

	if first == "" {
		t.Fatal("endpoint hash is empty")
	}
	if first != second {
		t.Fatalf("canonical endpoint hashes differ: %q != %q", first, second)
	}
	if first == other {
		t.Fatalf("distinct endpoint hashes collide: %q", first)
	}
	if first == "example/events" {
		t.Fatalf("endpoint hash leaked endpoint identity: %q", first)
	}
}

func TestVerifiedWebhookEndpointTelemetryRecordsOnlyAfterVerification(t *testing.T) {
	endpointHash := webhookEndpointMetricHash(testNamespace, testSecretName)
	mode := webhookReceiptModeLabel(false)
	acceptedBefore := testutil.ToFloat64(connectorWebhookVerifiedEndpointResponsesTotal.WithLabelValues(endpointHash, "accepted", mode))
	inflightBefore := testutil.ToFloat64(connectorWebhookVerifiedEndpointInflight.WithLabelValues(endpointHash, mode))

	verified := dispatcherWithVerifier(&fakeVerifier{}, []byte("secret"))
	response := postRequest(verified, testNamespace, testSecretName, `{"event":"contact.created"}`)
	if response.Code != http.StatusAccepted {
		t.Fatalf("verified response = %d, want 202", response.Code)
	}
	if got := testutil.ToFloat64(connectorWebhookVerifiedEndpointResponsesTotal.WithLabelValues(endpointHash, "accepted", mode)); got != acceptedBefore+1 {
		t.Fatalf("accepted responses = %v, want %v", got, acceptedBefore+1)
	}
	if got := testutil.ToFloat64(connectorWebhookVerifiedEndpointInflight.WithLabelValues(endpointHash, mode)); got != inflightBefore {
		t.Fatalf("inflight = %v, want %v after response", got, inflightBefore)
	}

	unauthenticated := dispatcherWithVerifier(&fakeVerifier{err: errBadSig}, []byte("secret"))
	response = postRequest(unauthenticated, testNamespace, testSecretName, `{"event":"contact.created"}`)
	if response.Code != http.StatusUnauthorized {
		t.Fatalf("unverified response = %d, want 401", response.Code)
	}
	if got := testutil.ToFloat64(connectorWebhookVerifiedEndpointResponsesTotal.WithLabelValues(endpointHash, "accepted", mode)); got != acceptedBefore+1 {
		t.Fatalf("unauthenticated request created endpoint telemetry: accepted responses = %v, want %v", got, acceptedBefore+1)
	}
}

func TestIngressPolicyReadbackUsesBoundedConfig(t *testing.T) {
	dispatcher := &Dispatcher{
		receiptsEnabled:             func() bool { return true },
		verificationGate:            newWebhookIngressCapacityGateWithWait(7, 4*time.Second, 9, 250*time.Millisecond),
		ingressAckDropEndpointCount: 2,
		ackDropTimeout:              750 * time.Millisecond,
	}

	got := dispatcher.ingressPolicyReadback()
	if !got.verifiedIngressReceipts || got.verificationLimit != 7 || got.verificationWaitLimit != 9 || got.verificationWaitMillis != 250 || got.retryAfterSeconds != 4 || got.ackDropEndpointCount != 2 || got.ackDropTimeoutMillis != 750 {
		t.Fatalf("unexpected policy readback: %+v", got)
	}
}
