import type { SanitizedConfig } from "payload";
import type { ITracer, ILogger } from "../instrumentation";
import type { IJobQueue } from "../jobs";
import type {
  EventBusProtocol,
  RealtimeBroadcasterProtocol,
  RealtimeRegistryProtocol,
  MetricsProtocol,
  AuditLogProtocol,
} from "./bind-protocols";

/** Always-present fields. Feature binders rely on these unconditionally. */
type BindContextBase = {
  tracer: ITracer;
  logger: ILogger;
};

/**
 * Optional cross-cutting deps. Generics let the app aggregator narrow the
 * shape to full interfaces (`IEventBus`, `IRealtimeBroadcaster`, `IMetrics`,
 * `IAuditLog`, etc.); feature binders see only the protocol surface, which is
 * enough for the methods they call. When an optional core package is absent the
 * corresponding generic defaults to its protocol type, and `ctx.bus` /
 * `ctx.realtime` / `ctx.metrics` / `ctx.auditLog` are undefined at runtime.
 *
 * The 4th generic `Metrics` and 5th generic `Audit` both default to their
 * protocol types so existing call sites that pass fewer explicit args remain
 * backward-compatible.
 */
export type BindContext<
  Bus extends EventBusProtocol = EventBusProtocol,
  Realtime extends RealtimeBroadcasterProtocol = RealtimeBroadcasterProtocol,
  RealtimeReg extends RealtimeRegistryProtocol = RealtimeRegistryProtocol,
  Metrics extends MetricsProtocol = MetricsProtocol,
  Audit extends AuditLogProtocol = AuditLogProtocol,
> = BindContextBase & {
  bus?: Bus;
  queue?: IJobQueue;
  realtime?: Realtime;
  realtimeRegistry?: RealtimeReg;
  metrics?: Metrics;
  auditLog?: Audit;
};

/** Production binders also receive the resolved Payload config. */
export type BindProductionContext<
  Bus extends EventBusProtocol = EventBusProtocol,
  Realtime extends RealtimeBroadcasterProtocol = RealtimeBroadcasterProtocol,
  RealtimeReg extends RealtimeRegistryProtocol = RealtimeRegistryProtocol,
  Metrics extends MetricsProtocol = MetricsProtocol,
  Audit extends AuditLogProtocol = AuditLogProtocol,
> = BindContext<Bus, Realtime, RealtimeReg, Metrics, Audit> & {
  config: SanitizedConfig;
};
