package run

import (
	"encoding/json"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	store "github.com/tidbcloud/AgentTeam/internal/store/workflow/run"
	runkernel "github.com/tidbcloud/AgentTeam/internal/workflow/run"
)

// ---------------------------------------------------------------------------
// Byte-exact identity validation regressions (#t2587).
//
// Every identity-bearing and closed-vocabulary envelope field is validated
// against the ORIGINAL producer bytes — whitespace-padded, invalid-UTF-8
// (post JSON-decoding U+FFFD, or raw invalid bytes), case/punctuation/token-
// bearing, and wrong-family values MUST fail closed (dropped), never normalized
// into an accepted identity. Bounded normalization is preserved ONLY for
// documented public prose (run_canceled.reason) and timestamps (retryAt/
// completedAt), which are not identities.
// ---------------------------------------------------------------------------

const (
	validEffectID         = "wfx_baa86a9e8b16589a778ee2cfce0bef62"
	validNotificationID   = "btn_baa86a9e8b16589a778ee2cfce0bef62"
	validKernelActivation = "a00000000000000000001"
	validAgentID          = "agt_000000000000ok"
	validUserID           = "usr_000000000000ok"
	validRawMemberID      = "abcdefghijkl"
	valid32HexMessageID   = "baa86a9e8b16589a778ee2cfce0bef62"
)

// identityValidator is a concrete envelope field validator and its producer
// family label.
type identityValidator struct {
	name      string
	validate  func(raw any) (any, bool)
	valid     any
	validText string
	// wrongFamily is a concrete value from a DIFFERENT identity family that the
	// validator must reject (e.g. a member id passed as a message id).
	wrongFamily string
}

// identityFamilies returns the exhaustive identity/closed-vocabulary validator
// families with their exact valid producer value.
func identityFamilies() []identityValidator {
	return []identityValidator{
		{name: "kernelActivationId", validate: envelopeFieldKernelActivationID(readEnvelopeIDRunes), valid: validKernelActivation, validText: validKernelActivation, wrongFamily: "b00000000000000000001"},
		{name: "messageId-raw32hex", validate: envelopeFieldMessageID(readEnvelopeIDRunes), valid: valid32HexMessageID, validText: valid32HexMessageID, wrongFamily: validRawMemberID},
		{name: "messageId-legacy-msg_", validate: envelopeFieldMessageID(readEnvelopeIDRunes), valid: "msg_1", validText: "msg_1", wrongFamily: "msg_1=SECRET"},
		{name: "effectId", validate: envelopeFieldStableChildID(validEffectIDPrefix, readEnvelopeIDRunes), valid: validEffectID, validText: validEffectID, wrongFamily: validAgentID},
		{name: "notificationId", validate: envelopeFieldStableChildID(validNotificationIDPrefix, readEnvelopeIDRunes), valid: validNotificationID, validText: validNotificationID, wrongFamily: validRawMemberID},
		{name: "agentId", validate: envelopeFieldEntityID(validAgentIDPrefix, readEnvelopeIDRunes), valid: validAgentID, validText: validAgentID, wrongFamily: validUserID},
		{name: "userId", validate: envelopeFieldEntityID(validUserIDPrefix, readEnvelopeIDRunes), valid: validUserID, validText: validUserID, wrongFamily: validEffectID},
		{name: "rawMemberId", validate: envelopeFieldRawMemberID(readEnvelopeIDRunes), valid: validRawMemberID, validText: validRawMemberID, wrongFamily: valid32HexMessageID},
		{name: "identifier", validate: envelopeFieldIdentifier(readEnvelopeIDRunes), valid: "wnd_send", validText: "wnd_send", wrongFamily: "wnd#send"},
		{name: "enum-kind", validate: envelopeFieldEnum(eventEnvelopeKindValues), valid: "run_started", validText: "run_started", wrongFamily: "run started"},
		{name: "enum-decision", validate: envelopeFieldEnum(eventEnvelopeDecisionValues), valid: "approved", validText: "approved", wrongFamily: "Approved"},
		{name: "enum-status", validate: envelopeFieldEnum(eventEnvelopeStatusValues), valid: "running", validText: "running", wrongFamily: "running "},
		{name: "plan-port", validate: envelopeFieldPlanPort, valid: "output", validText: "output", wrongFamily: "out put"},
	}
}

// adversarialIdentities are the byte-level mutations that MUST fail closed for
// every identity/closed-vocabulary family. `want` describes why.
func adversarialIdentities(valid string) map[string]string {
	first := string(valid[0])
	validNoFirst := valid[1:]
	return map[string]string{
		"leading-space":                " " + valid,
		"trailing-space":               valid + " ",
		"surrounding-utf8-replacement": "�" + valid + "�",
		"internal-utf8-replacement":    valid[:1] + "�" + valid[1:],
		"uppercase-first":              uppercaseFirst(valid),
		"token-bearing":                valid + "=SECRET",
		"punctuation-dot":              first + "." + validNoFirst,
		"punctuation-slash":            first + "/" + validNoFirst,
	}
}

func uppercaseFirst(value string) string {
	if value == "" {
		return value
	}
	b := []byte(value)
	if b[0] >= 'a' && b[0] <= 'z' {
		b[0] = b[0] - 'a' + 'A'
	}
	return string(b)
}

// TestIdentityValidatorsByteExactFailClosed proves every identity/closed-vocab
// validator accepts the exact producer bytes and FAILS CLOSED on every
// byte-level mutation (padding, invalid UTF-8, case, token, punctuation, wrong
// family). The returned value must equal the input byte-for-byte — never a
// normalized variant.
func TestIdentityValidatorsByteExactFailClosed(t *testing.T) {
	for _, fam := range identityFamilies() {
		t.Run(fam.name, func(t *testing.T) {
			// Exact producer bytes pass and are returned unchanged.
			out, ok := fam.validate(fam.valid)
			require.True(t, ok, "%s valid %q must pass", fam.name, fam.valid)
			require.Equal(t, fam.validText, out, "%s must return the exact producer value", fam.name)

			// A value from a different identity family fails closed.
			if fam.wrongFamily != "" {
				_, ok := fam.validate(fam.wrongFamily)
				require.False(t, ok, "%s must fail closed for wrong-family %q", fam.name, fam.wrongFamily)
			}

			// Every byte-level mutation fails closed. The generic identifier
			// grammar legitimately allows uppercase, so skip the uppercase-first
			// adversarial only for that family.
			for label, mutated := range adversarialIdentities(fam.validText) {
				if label == "uppercase-first" && fam.name == "identifier" {
					continue
				}
				t.Run(label, func(t *testing.T) {
					_, ok := fam.validate(mutated)
					require.False(t, ok, "%s must fail closed for %s=%q (never normalize into an accepted identity)", fam.name, label, mutated)
				})
			}
		})
	}
}

// TestIdentityValidatorsRawInvalidUTF8FailClosed proves direct validator calls
// with raw invalid-UTF-8 Go bytes (0x80..0xFF) fail closed — the byte stream is
// the identity, and a malformed byte is never ToValidUTF8'd into a lookalike.
func TestIdentityValidatorsRawInvalidUTF8FailClosed(t *testing.T) {
	for _, fam := range identityFamilies() {
		t.Run(fam.name, func(t *testing.T) {
			for _, offset := range []int{0, 1} {
				b := []byte(fam.validText)
				if len(b) <= offset {
					continue
				}
				b[offset] = 0xff
				_, ok := fam.validate(string(b))
				require.False(t, ok, "%s must fail closed for a raw invalid-UTF-8 byte at offset %d", fam.name, offset)
			}
		})
	}
}

// TestEventEnvelopeIdentityProjectionByteExact proves the JSON projection path
// drops padded / U+FFFD / wrong-family identities from a message_callback_awaiting
// event while preserving the exact producer identities.
func TestEventEnvelopeIdentityProjectionByteExact(t *testing.T) {
	now := time.Now().UTC()
	event := store.Event{
		ID: "wre_1", RunID: "wri_1", Seq: 1, Type: "message_callback_awaiting",
		PayloadJSON: json.RawMessage(`{
			"effectId":"wfx_baa86a9e8b16589a778ee2cfce0bef62","activationId":"a00000000000000000001","nodeId":"wnd_cb","kind":"send_message",
			"messageId":"msg_1","callbackResponderAgentId":"agt_000000000000ok",
			"deliveryScope":{"kind":"task","scopeId":"tsk_1"},
			"wakeAgentIds":["agt_000000000000ok"],
			"paddedEffectId":" wfx_baa86a9e8b16589a778ee2cfce0bef62 ",
			"paddedActivationId":"a00000000000000000001 ",
			"utf8EffectId":"wfx_baa86a9e8b16589a778ee2cfce0bef62�",
			"wrongFamilyMessageId":"wfx_baa86a9e8b16589a778ee2cfce0bef62"
		}`),
		CreatedAt: now,
	}
	log := RunLogResponse(event)
	text := string(log.Details)
	// Exact producer identities survive.
	require.Contains(t, text, `"effectId":"wfx_baa86a9e8b16589a778ee2cfce0bef62"`)
	require.Contains(t, text, `"activationId":"a00000000000000000001"`)
	require.Contains(t, text, `"messageId":"msg_1"`)
	require.Contains(t, text, `"callbackResponderAgentId":"agt_000000000000ok"`)
	require.Contains(t, text, `"scopeId":"tsk_1"`)
	// The padded / U+FFFD / wrong-family variants (present as unknown context keys
	// whose values never make it into a reviewed context field) are dropped.
	require.NotContains(t, text, "paddedEffectId")
	require.NotContains(t, text, "paddedActivationId")
	require.NotContains(t, text, "utf8EffectId")
	require.NotContains(t, text, "wrongFamilyMessageId")
}

// TestEventEnvelopeActorIdentityByteExact proves the actor {type,id,memberId}
// closed vocabulary rejects padded / U+FFFD / wrong-family actor identities.
func TestEventEnvelopeActorIdentityByteExact(t *testing.T) {
	valid := map[string]any{"type": "agent", "id": validAgentID, "memberId": validRawMemberID}
	out, ok := envelopeFieldActor(valid)
	require.True(t, ok, "exact actor must pass")
	require.Equal(t, map[string]any{"type": "agent", "id": validAgentID, "memberId": validRawMemberID}, out)

	adversarial := []map[string]any{
		{"type": " agent", "id": validAgentID, "memberId": validRawMemberID},
		{"type": "agent", "id": " " + validAgentID, "memberId": validRawMemberID},
		{"type": "agent", "id": validAgentID, "memberId": validRawMemberID + " "},
		{"type": "agent", "id": validAgentID + "�", "memberId": validRawMemberID},
		{"type": "agent", "id": "usr_" + validAgentID[4:], "memberId": validRawMemberID},
		{"type": "agent", "id": validAgentID, "memberId": "mem_" + validRawMemberID},
		{"type": "agent", "id": validAgentID + "=SECRET", "memberId": validRawMemberID},
		{"type": "human", "id": validAgentID, "memberId": validRawMemberID},
	}
	for index, actor := range adversarial {
		_, ok := envelopeFieldActor(actor)
		require.Falsef(t, ok, "actor case %d must fail closed: %v", index, actor)
	}
}

// TestEventEnvelopeScopeIdentityByteExact proves the scope {kind,scopeId} closed
// vocabulary rejects padded / U+FFFD / wrong-vocabulary scope identities.
func TestEventEnvelopeScopeIdentityByteExact(t *testing.T) {
	valid := map[string]any{"kind": "task", "scopeId": "tsk_1"}
	out, ok := envelopeFieldScope(valid)
	require.True(t, ok, "exact scope must pass")
	require.Equal(t, map[string]any{"kind": "task", "scopeId": "tsk_1"}, out)

	adversarial := []map[string]any{
		{"kind": " task", "scopeId": "tsk_1"},
		{"kind": "task", "scopeId": " tsk_1"},
		{"kind": "task", "scopeId": "tsk_1�"},
		{"kind": "task", "scopeId": "Tsk_1"},
		{"kind": "task", "scopeId": "tsk_1=SECRET"},
		{"kind": "Task", "scopeId": "tsk_1"},
	}
	for index, scope := range adversarial {
		_, ok := envelopeFieldScope(scope)
		require.Falsef(t, ok, "scope case %d must fail closed: %v", index, scope)
	}
}

// TestEffectResultIdentityBytesByteExact proves EffectResult identity fields
// (failure code/stage/path, workItem key/dependencyPath, diagnostic field) fail
// closed on byte-level mutations and never normalize into an accepted identity.
func TestEffectResultIdentityBytesByteExact(t *testing.T) {
	// Direct identity validators are byte-exact; the projection never trims
	// before validating them.
	if _, ok := runkernel.PublicFailureCode("message.delivery_failed"); !ok {
		t.Fatal("exact failure code must pass")
	}
	for _, bad := range []string{" message.delivery_failed", "message.delivery_failed ", "message.delivery_failed�", "Message.delivery_failed", "message.delivery_failed=SECRET", "message..delivery_failed"} {
		if _, ok := runkernel.PublicFailureCode(bad); ok {
			t.Errorf("failure code %q must fail closed byte-exact", bad)
		}
	}
	// WorkItem key grammar is byte-exact.
	if _, ok := runkernel.PublicWorkItemKey("wi_1"); !ok {
		t.Fatal("exact workItem key must pass")
	}
	for _, bad := range []string{" wi_1", "wi_1 ", "wi_1�", "Wi_1", "wi.1"} {
		if _, ok := runkernel.PublicWorkItemKey(bad); ok {
			t.Errorf("workItem key %q must fail closed byte-exact", bad)
		}
	}
	// Diagnostic field-name identity is byte-exact (camelCase is allowed, so
	// uppercase is NOT an adversarial for this grammar).
	for _, bad := range []string{" field", "field ", "field�", "field=SECRET", "field.name"} {
		if _, ok := runkernel.PublicDiagnosticField(bad); ok {
			t.Errorf("diagnostic field %q must fail closed byte-exact", bad)
		}
	}
}
