package push

import "encoding/json"

// Event is the typed contract for client events emitted onto the gRPC
// push stream. Implementations carry their own serialiser; push.Service
// invokes Marshal at publish time to obtain the bytes that go into
// `pushv1.ClientEvent.Payload`.
//
// Notification dispatcher builds a typed FlatBuffers Event for every
// catalog kind through `notification.buildClientPushEvent`, backed by
// the per-kind helpers in `pkg/transcoder/notification.go`. JSONEvent
// (below) remains the safety net for kinds that arrive without a
// catalog schema.
type Event interface {
	// Kind returns the catalog kind of this event (`backend/README.md`
	// §10). Empty kind is rejected at publish time.
	Kind() string

	// Marshal returns the bytes that travel inside
	// `pushv1.ClientEvent.Payload`. Implementations are expected to use
	// FlatBuffers (preferred) or any deterministic encoding the client
	// can decode; the push transport treats the result as opaque
	// payload bytes.
	Marshal() ([]byte, error)
}

// JSONEvent is the safety-net Event implementation for kinds that
// arrive without a catalog FlatBuffers schema. It serialises Payload
// via encoding/json so a misconfigured producer cannot silently drop
// events while a new kind is being added.
//
// New kinds must ship with a typed FlatBuffers schema in
// `pkg/schema/fbs/notification.fbs` and a matching case in
// `notification.buildClientPushEvent`; JSONEvent is not a canonical
// shape, only a fallback.
type JSONEvent struct {
	// EventKind is the catalog kind returned by Kind().
	EventKind string

	// Payload is the JSON-serialisable map written by the producer.
	Payload map[string]any
}

// Kind returns EventKind verbatim.
func (e JSONEvent) Kind() string { return e.EventKind }

// Marshal returns Payload encoded as JSON. The result is treated as
// opaque bytes by the push transport.
func (e JSONEvent) Marshal() ([]byte, error) {
	return json.Marshal(e.Payload)
}

var _ Event = JSONEvent{}
