package impl

import (
	"strings"
	"testing"

	"github.com/stretchr/testify/require"
)

// TestSanitizeChildMessageRedactsSinkCredentials covers the leak the caller
// cannot prevent: a TiCDC kernel error embeds the S3 sink URI, this service
// puts the secret access key in that URI's query string, and the observer only
// ever holds that key as ciphertext - so it can never be passed in as a literal
// to redact. Get and List return this message verbatim.
func TestSanitizeChildMessageRedactsSinkCredentials(t *testing.T) {
	t.Parallel()

	const (
		accessKey = "AKIAEXAMPLETESTKEY"
		secretKey = "wJalrXUtnFEMItestSECRETkey"
	)
	message := "[CDC:ErrS3SinkFailed] write failed: " +
		"s3://bucket/prefix?access-key=" + accessKey +
		"&secret-access-key=" + secretKey +
		"&endpoint=https://s3.test.invalid"

	got := sanitizeChildMessage(message, "test-access-key-id")

	require.NotContains(t, got, secretKey, "the S3 secret must never reach the read model")
	require.NotContains(t, got, accessKey)
	require.Contains(t, got, "secret-access-key=[REDACTED]")
	require.Contains(t, got, "access-key=[REDACTED]")
	// The message still has to be useful to whoever is debugging it.
	require.Contains(t, got, "[CDC:ErrS3SinkFailed]")
	require.Contains(t, got, "endpoint=https://s3.test.invalid")
}

func TestSanitizeChildMessageRedactsBeforeTruncating(t *testing.T) {
	t.Parallel()

	const secretKey = "wJalrXUtnFEMItestSECRETkey"
	// Push the credential past the truncation boundary so a truncate-first
	// implementation would keep it.
	message := strings.Repeat("x", 2100) + " secret-access-key=" + secretKey

	got := sanitizeChildMessage(message)

	require.NotContains(t, got, secretKey)
	require.LessOrEqual(t, len(got), 2048)
}

func TestSanitizeChildMessageStillRedactsCallerSuppliedValues(t *testing.T) {
	t.Parallel()

	got := sanitizeChildMessage("connect failed for user test-user", "test-user")
	require.NotContains(t, got, "test-user")
	require.Contains(t, got, "[REDACTED]")
}
