import type {
  AttachConversation,
  ConversationSnapshot,
  DetachConversation,
  HarnessConversationService,
  HarnessEventEnvelope,
  SendHarnessTurn,
  TurnReceipt,
} from '@mosaicstack/types';
import type { ChatRuntime } from './chat-runtime.js';

/**
 * The `pi-rpc` chat runtime. It executes browser chat exclusively through the
 * harness-neutral {@link HarnessConversationService} RPC boundary — it never
 * touches the embedded `AgentService`/`ProviderService`/`RoutingEngineService`
 * stack, and it forwards the caller's exact selection tuple and idempotency key
 * without substitution.
 *
 * It owns no state and adds no policy: every method forwards the caller's exact
 * argument to the injected {@link HarnessConversationService} and returns its
 * result unchanged, so the requested selection tuple and idempotency key can
 * never be substituted on the way through.
 */
export class HarnessChatRuntime implements ChatRuntime {
  readonly kind = 'harness' as const;

  constructor(private readonly conversations: HarnessConversationService) {}

  attach(input: AttachConversation & { afterSequence?: number }): Promise<ConversationSnapshot> {
    return this.conversations.attach(input);
  }

  detach(input: DetachConversation): Promise<void> {
    return this.conversations.detach(input);
  }

  send(input: SendHarnessTurn & { idempotencyKey: string }): Promise<TurnReceipt> {
    return this.conversations.send(input);
  }

  subscribeFrom(
    conversationId: string,
    afterSequence: number,
  ): AsyncIterable<HarnessEventEnvelope> {
    return this.conversations.subscribeFrom(conversationId, afterSequence);
  }
}
