// src/engine/core/IMatrixContext.ts

import type { ITransportAdapter } from '../remoting/ITransportAdapter';
import type { IMatrixRuntime } from './IMatrixRuntime';
import type { IComponentRegistryLike } from './IComponentRegistryLike';
import type { ILispEnvironment } from './ILispEnvironment';
import type { ISecurityRealm } from '../../core/security/ISecurityRealm';

/**
 * Unified context interface for Matrix components.
 *
 * This replaces the previous split between IFabricContext and ServiceScope
 * by combining identity (mount) with dependency injection (transport, registry, runtime).
 *
 * Key principles:
 * - NO SINGLETONS: All dependencies are injected through context
 * - Hierarchical: Child contexts derived from parent with extended mount path
 * - Transport-agnostic: Transport adapter is injected, not resolved globally
 */
export interface IMatrixContext {
  /**
   * Component identity in the supervision hierarchy.
   * Format: dot-delimited path segments.
   * Examples: "", "daemon", "app.db", "app.ui.form"
   *
   * Does NOT include root or scheme prefix.
   * Root is a transport concern, not a component concern.
   */
  readonly mount: string;

  /**
   * Transport adapter for this context's scheme.
   * All messaging goes through this adapter.
   */
  readonly transport: ITransportAdapter;

  /**
   * Optional parent context reference for upward traversal.
   */
  readonly parent?: IMatrixContext;

  /**
   * Runtime for creating child components.
   *
   * ⚠️ REQUIRED for UI Control Inversion pattern.
   * Actors call runtime.createChild() instead of new ComponentClass().
   * See: UI-CONTROL-INVERSION.md
   */
  readonly runtime: IMatrixRuntime;

  /**
   * Optional component registry (injected, not singleton).
   * Hierarchical - child registries inherit from parent.
   */
  readonly registry?: IComponentRegistryLike;

  /**
   * Optional LISP environment for dual dispatch.
   *
   * When present, the actor loop checks for LISP handlers BEFORE
   * falling back to TypeScript handlers. This enables:
   * - Hot-reloadable handlers
   * - Homoiconic component definitions (defactor)
   * - Mixed TS/LISP components
   */
  readonly lispEnv?: ILispEnvironment;

  /**
   * Optional security realm for message verification.
   *
   * Vision 27: "Supervision tree = Security tree."
   * When present, ActorBehavior verifies messages before dispatch.
   *
   * Joe Armstrong (Erlang, "Programming Erlang"):
   *   "Every message must be verified at the boundary."
   *
   * Mark Miller (Capability Security, E Language):
   *   "The receiver decides whether to trust the sender."
   */
  readonly securityRealm?: ISecurityRealm;

  /**
   * Optional fact-plane publish hook.
   *
   * Implementations may bridge this to request/reply against a blackboard actor,
   * direct storage calls, or another transport-specific mechanism.
   * Omit this hook in contexts that do not support fact publishing.
   *
   * @param domain - Fact domain key (e.g., "market.tsla")
   * @param data - Fact payload
   * @param source - Mount path of the emitting actor
   * @returns Monotonic revision for the domain
   */
  publishFact?(domain: string, data: Record<string, unknown>, source: string): Promise<number>;

  /**
   * Optional fact-plane read hook.
   *
   * Omit this hook in contexts that do not support fact reads.
   *
   * @param domain - Fact domain key (e.g., "market.tsla")
   * @returns Latest fact payload and revision, or null if missing
   */
  readFact?(domain: string): Promise<{ data: unknown; revision: number } | null>;

  /**
   * Optional fact-plane subscription hook.
   *
   * Omit this hook in contexts that do not support push subscriptions.
   *
   * @param domain - Fact domain key (e.g., "market.tsla")
   * @param handler - Callback for fact payload updates
   * @returns Unsubscribe function
   */
  subscribeFact?(domain: string, handler: (data: unknown) => void): () => void;

  /**
   * Derive a child context by appending a segment to the mount path.
   * The child inherits transport, runtime, and registry from parent.
   *
   * @param segment - Path segment to append (e.g., "child1")
   * @returns New context with extended mount path
   */
  derive(segment: string): IMatrixContext;

  /**
   * Get a service from the context's registry.
   * Returns undefined if service not found.
   */
  getService<T>(key: string | symbol): T | undefined;

  /**
   * Register a service in this context's registry.
   * Services are available to this context and its descendants.
   */
  setService<T>(key: string | symbol, service: T): void;

  /**
   * Resolve a system service by walking the mount hierarchy on the wire.
   *
   * Tries getService() first (synchronous, in-process). If not found,
   * uses ServiceCascadeResolver to probe the mount tree via $ping/$pong.
   * Caches the result in the service registry for subsequent sync lookups.
   *
   * @param service - Service name (e.g., 'llm', 'component-store')
   * @returns Resolved service mount path (e.g., 'system.llm')
   */
  resolveServiceAsync?(service: string): Promise<string>;

  /**
   * Resolve a service by contract — walks the intent provider chain.
   *
   * Provider #1: Context cascade (pre-cached, instant)
   * Provider #2+: Bus scan, federation, semantic (future)
   *
   * First match wins. Result is cached in context for instant
   * subsequent lookups. Returns undefined if no provider has it.
   *
   * @param contract - The service contract to resolve
   * @returns Typed service proxy or undefined
   */
  resolve?(contract: import('./ServiceContract').ServiceContract): Promise<import('./ServiceContract').IActorService | undefined>;
}
