/**
 * Minimal protocol surfaces used by feature binders to interact with optional
 * cross-cutting infrastructure (event bus, realtime broadcaster, realtime
 * handler registry, metrics, audit log). Lives in `core-shared` so `BindContext`
 * can reference these unconditionally — features depend on `core-shared`, never
 * on the optional packages directly.
 *
 * The optional packages' full interfaces (`IEventBus`, `IRealtimeBroadcaster`,
 * `IRealtimeHandlerRegistry`, `IMetrics`, `IAuditLog`) `extends` these —
 * typechecks fail if a refactor narrows the protocol surface in a way the full
 * interface would lose.
 */
import type { AuditEntry } from "../audit/audit-entry";

export type EventBusProtocol = {
  publish<T>(event: { name: string }, payload: T): Promise<void>;
  subscribe<T>(
    event: { name: string },
    consumer: string,
    handler: (payload: T) => Promise<void>,
  ): void;
};

export type RealtimeBroadcasterProtocol = {
  broadcast<T>(
    channel: { name: string; key?: unknown },
    payload: T,
  ): Promise<void>;
};

export type RealtimeRegistryProtocol = {
  register(entry: { descriptor: unknown; handler: unknown }): void;
  registerChannel(descriptor: unknown): void;
  listChannels(): unknown[];
};

/**
 * Minimal metrics protocol surface. `IMetrics` in `core-shared/instrumentation`
 * extends this — typechecks fail if `IMetrics` is narrowed below this surface.
 * Feature binders that receive `ctx.metrics` see only this protocol type.
 */
export type MetricsProtocol = {
  counter(
    name: string,
    value?: number,
    attributes?: Record<string, string | number | boolean>,
  ): void;
  histogram(
    name: string,
    value: number,
    attributes?: Record<string, string | number | boolean>,
  ): void;
  gauge(
    name: string,
    value: number,
    attributes?: Record<string, string | number | boolean>,
  ): void;
};

/**
 * Minimal audit-log protocol surface. `IAuditLog` (in optional `@repo/core-audit`)
 * extends this — typechecks fail if narrowed below. Feature binders that
 * receive `ctx.auditLog` see only this protocol type.
 *
 * `eraseSubject` is NOT on the protocol — it's a privileged op exposed only
 * on the full `IAuditLog` interface in the optional package.
 */
export type AuditLogProtocol = {
  record(entry: AuditEntry): Promise<void>;
};
