package httpapi

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/easyai/easyai-ai-gateway/apps/api/internal/auth"
	"github.com/easyai/easyai-ai-gateway/apps/api/internal/identity"
	ssfreceiver "github.com/easyai/easyai-ai-gateway/apps/api/internal/securityevents"
)

func TestSecurityEventConnectionTraceAndAuditProjection(t *testing.T) {
	request := httptest.NewRequest(http.MethodPut, "/connection", nil)
	request.Header.Set("Authorization", "Bearer must-not-escape")
	recorder := httptest.NewRecorder()
	traceID := ensureSecurityEventTraceID(recorder, request)
	if traceID == "" || recorder.Header().Get("X-Trace-Id") != traceID {
		t.Fatalf("trace header=%q trace=%q", recorder.Header().Get("X-Trace-Id"), traceID)
	}
	actor := &auth.User{ID: "admin-id", Username: "admin", Source: "local", Roles: []string{"manager"}}
	connection := ssfreceiver.ConnectionView{ConnectionID: "connection-id", LifecycleStatus: "error", HealthMode: "introspection_fallback"}
	input := securityEventConnectionAuditInput(request, actor, "connect", "failure", "management_token_failed", traceID, connection)
	payload, err := json.Marshal(input)
	if err != nil {
		t.Fatal(err)
	}
	if input.Action != "identity.security_event_connection.connect" || input.TargetID != "connection-id" || input.Metadata["traceId"] != traceID {
		t.Fatalf("audit input=%#v", input)
	}
	for _, forbidden := range []string{"must-not-escape", "authorization_header", "push_bearer", "credential_ref"} {
		if strings.Contains(strings.ToLower(string(payload)), forbidden) {
			t.Fatalf("audit payload exposed forbidden field %q: %s", forbidden, payload)
		}
	}
}

func TestSecurityEventConnectionWriteHeaders(t *testing.T) {
	request := httptest.NewRequest(http.MethodPost, "/connection/verify", nil)
	recorder := httptest.NewRecorder()
	if _, ok := requiredConnectionIdempotencyKey(recorder, request); ok || recorder.Code != http.StatusBadRequest {
		t.Fatalf("missing Idempotency-Key status=%d", recorder.Code)
	}
	request = httptest.NewRequest(http.MethodPut, "/connection", nil)
	recorder = httptest.NewRecorder()
	if matchConnectionVersion(recorder, request, 0) || recorder.Code != http.StatusPreconditionRequired {
		t.Fatalf("initial connection without If-Match status=%d", recorder.Code)
	}
	request.Header.Set("If-Match", `W/"0"`)
	recorder = httptest.NewRecorder()
	if !matchConnectionVersion(recorder, request, 0) {
		t.Fatalf("initial zero version was rejected: status=%d", recorder.Code)
	}

	request = httptest.NewRequest(http.MethodPost, "/connection/verify", nil)
	request.Header.Set("If-Match", `W/"7"`)
	recorder = httptest.NewRecorder()
	if !matchConnectionVersion(recorder, request, 7) {
		t.Fatalf("valid weak ETag was rejected: status=%d", recorder.Code)
	}

	request.Header.Set("If-Match", `"6"`)
	recorder = httptest.NewRecorder()
	if matchConnectionVersion(recorder, request, 7) || recorder.Code != http.StatusPreconditionFailed {
		t.Fatalf("stale ETag status=%d", recorder.Code)
	}
	if normalizedConnectionETag(`W/"7"`) != "7" ||
		securityEventOperationHash("verify", "7") == securityEventOperationHash("verify", "8") {
		t.Fatal("security event idempotency request fingerprint is not stable")
	}
}

func TestSecurityEventPrerequisitesNeverExposeSecrets(t *testing.T) {
	server := &Server{identityTestRevision: identity.Revision{
		Issuer: "https://auth.example/issuer/shared", TenantID: "stable-tenant",
		MachineClientID: "gateway-machine", MachineCredentialRef: "identity-machine-test",
		PublicBaseURL: "https://gateway.example",
	}}
	payload, err := json.Marshal(server.securityEventPrerequisites())
	if err != nil {
		t.Fatal(err)
	}
	if strings.Contains(string(payload), "must-not-escape") || strings.Contains(strings.ToLower(string(payload)), "secret") {
		t.Fatalf("secret escaped in prerequisites: %s", payload)
	}
}
