package run

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

	"github.com/stretchr/testify/require"

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

// This file exercises EVERY production event kind with its exact producer-shaped
// payload through the storage / history / follow / log projection surfaces
// (RunLogResponse for the Run log and EventResponse for the event/follow
// surface). The payload for each kind is derived mechanically from the
// producer-emitted field set (discoverProducerEventFieldSets) so the exercise
// uses the real producer truth, not a hand-written fixture list. It proves the
// closed per-kind schema carries every producer field, never leaks an
// operational/secret key, and projects the failure contract exactly on
// failure-capable kinds.

// producerFieldJSONValue returns a schema-valid JSON fragment for one
// reviewed producer context field, so an every-kind exercise can build an exact
// producer-shaped payload that must survive projection.
func producerFieldJSONValue(field string) string {
	switch field {
	case "effectId":
		return `"wfx_baa86a9e8b16589a778ee2cfce0bef62"`
	case "activationId":
		return `"a00000000000000000001"`
	case "nodeId":
		return `"wnd_1"`
	case "agentId":
		return `"agt_0000000000000a"`
	case "scopeId":
		return `"wsc_1"`
	case "port":
		return `"completed"`
	case "messageId":
		return `"0123456789abcdef0123456789abcdef"`
	case "notificationId":
		return `"btn_baa86a9e8b16589a778ee2cfce0bef62"`
	case "decision":
		return `"approved"`
	case "decidedByMemberId":
		return `"000000000002"`
	case "assigneeMemberId":
		return `"000000000001"`
	case "callbackResponderAgentId":
		return `"agt_0000000000000a"`
	case "retryAt":
		return `"2026-08-17T00:00:00Z"`
	case "receiptRecovery":
		return `true`
	case "wakeAgentIds":
		return `["agt_0000000000000a","agt_0000000000000b"]`
	case "deliveryScope":
		return `{"kind":"channel","scopeId":"chn_1"}`
	case "threadScope":
		return `{"kind":"thread","scopeId":"thr_1"}`
	case "reason":
		return `"canceled"`
	case "actor":
		return `{"type":"human","id":"usr_0000000000000a","memberId":"000000000001"}`
	case "status":
		return `"queued"`
	case "kind":
		return `"send_message"`
	case "waitingReason":
		return `"responder_capacity"`
	default:
		return `"reviewed_value"`
	}
}

// TestEveryProductionKindExactPayloadThroughStorageLogEvent proves every
// producer-emitted event kind, carrying the exact producer field set, survives
// the storage->log and storage->event/follow projection surfaces: every
// producer field projects, no operational/secret key leaks, and failure-capable
// kinds project their failure contract.
func TestEveryProductionKindExactPayloadThroughStorageLogEvent(t *testing.T) {
	discovered := discoverProducerEventFieldSets(t)
	kinds := discoverProducerEventKinds(t)
	require.NotEmpty(t, kinds, "the producer kind discovery must be non-empty")

	for _, producer := range kinds {
		t.Run(producer.kind, func(t *testing.T) {
			fields := discovered[producer.kind]
			var fieldsList []string
			if fields.fields != nil {
				for field := range fields.fields {
					if failureNamespaceFields[field] {
						continue
					}
					fieldsList = append(fieldsList, field)
				}
			}
			sort.Strings(fieldsList)

			var builder strings.Builder
			builder.WriteString(`{`)
			builder.WriteString(`"kind":"` + producer.kind + `"`)
			for _, field := range fieldsList {
				builder.WriteString(`,"` + field + `":` + producerFieldJSONValue(field))
			}
			if producer.failureCapable {
				builder.WriteString(`,"code":"message.delivery_failed","stage":"dispatch","path":"wnd_1","retryable":true`)
			}
			// Operational/secret key that must never survive projection.
			builder.WriteString(`,"leaseToken":"lease_secret"`)
			builder.WriteString(`}`)

			event := store.Event{
				ID: "wre_every", RunID: "wri_every", Seq: 1, Type: producer.kind,
				PayloadJSON: json.RawMessage(builder.String()), CreatedAt: time.Now().UTC(),
			}

			// Every producer-emitted non-failure context field must project.
			logText := string(RunLogResponse(event).Details)
			eventText := string(EventResponse(event).Payload)
			for _, field := range fieldsList {
				require.Contains(t, logText, `"`+field+`":`, "log projection must carry producer field %q for kind %q", field, producer.kind)
				require.Contains(t, eventText, `"`+field+`":`, "event projection must carry producer field %q for kind %q", field, producer.kind)
			}
			// Operational and secret keys must never leak.
			require.NotContains(t, logText, "leaseToken")
			require.NotContains(t, logText, "lease_secret")
			require.NotContains(t, eventText, "leaseToken")
			require.NotContains(t, eventText, "lease_secret")
			// The failure contract projects on failure-capable kinds.
			if producer.failureCapable {
				require.Contains(t, logText, `"code":"message.delivery_failed"`)
				require.Contains(t, eventText, `"code":"message.delivery_failed"`)
			}
			// Log and event surfaces must project identically.
			require.JSONEq(t, logText, eventText, "log and event surfaces must project identically for kind %q", producer.kind)
		})
	}
}

// TestEveryProductionKindExactPayloadFailureAndSecretInjection proves that even
// when a producer-shaped payload is seeded with secret-bearing lookalikes of
// reviewed fields (token values, oversized ids, prefixed members) the closed
// per-kind schema fails them closed, preserving only the reviewed producer
// fields.
func TestEveryProductionKindExactPayloadFailureAndSecretInjection(t *testing.T) {
	discovered := discoverProducerEventFieldSets(t)
	kinds := discoverProducerEventKinds(t)

	for _, producer := range kinds {
		t.Run(producer.kind, func(t *testing.T) {
			fields := discovered[producer.kind]
			if fields.fields == nil {
				return
			}
			seeded := map[string]bool{}
			for field := range fields.fields {
				if field == "kind" {
					continue
				}
				seeded[field] = true
			}
			if !seeded["effectId"] && !seeded["activationId"] && !seeded["scopeId"] {
				return
			}

			var builder strings.Builder
			builder.WriteString(`{`)
			builder.WriteString(`"kind":"` + producer.kind + `"`)
			first := true
			for field := range fields.fields {
				if field == "kind" || failureNamespaceFields[field] {
					continue
				}
				if !first {
					builder.WriteString(`,`)
				}
				first = false
				builder.WriteString(`"` + field + `":"token=SECRET"`)
			}
			builder.WriteString(`}`)

			event := store.Event{
				ID: "wre_inj", RunID: "wri_inj", Seq: 1, Type: producer.kind,
				PayloadJSON: json.RawMessage(builder.String()), CreatedAt: time.Now().UTC(),
			}
			text := string(RunLogResponse(event).Details)
			require.NotContains(t, text, "token=SECRET", "secret-bearing reviewed fields must fail closed for kind %q", producer.kind)
			require.NotContains(t, text, "SECRET", "secret-bearing reviewed fields must fail closed for kind %q", producer.kind)
		})
	}
}
