import type { AixWire_Particles } from '~/modules/aix/server/api/aix.wiretypes';


export type ParticleServerLogLevel = false | 'srv-log' | 'srv-warn';

export type ParticleCGDialectEndReason = Extract<AixWire_Particles.CGEndReason, 'done-dialect' | 'issue-dialect'>;

export interface IParticleTransmitter {

  // Parser-initiated Control //

  /** Set the end reason - only use for 'done-dialect' to signal a dialect-close */
  setDialectEnded(reason: ParticleCGDialectEndReason): void;

  /** End the current part and flush it, which also calls `setDialectEnded('issue-dialct')` */
  setDialectTerminatingIssue(dialectText: string, symbol: string | null, serverLog: ParticleServerLogLevel): void;

  /** Communicates the finish reason to the client - Data only, this does not do Control, like the above */
  setTokenStopReason(reason: AixWire_Particles.GCTokenStopReason): void;


  // Parts data //

  /** Closes the current part, also flushing it out */
  endMessagePart(): void;

  /** Appends text, creating a part if missing [throttled] */
  appendText(textChunk: string): void;

  /** Appends reasoning text, creating a part if missing [throttled] */
  appendReasoningText(textChunk: string, options?: { weak?: 'tag', restart?: boolean }): void;

  /** Sets a reasoning signature, associated with the current reasoning text */
  setReasoningSignature(signature: string): void;

  /** Adds a raw (redacted) reasoning data parcel */
  addReasoningRedactedData(data: string): void;

  /** Appends test, with automatic heuristics for Particle splitting [throttled] */
  appendAutoText_weak(textChunk: string): void;

  /** Appends an audio file generated by the model */
  appendAudioInline(mimeType: string, base64Data: string, label: string, generator: string, durationMs: number): void;

  /** Appends an image generated by the model */
  appendImageInline(mimeType: string, base64Data: string, label: string, generator: string, prompt: string): void;

  /**
   * Creates a FC part, flushing the previous one if needed, and starts adding data to it
   * @param id if null [Gemini], a new id will be generated to keep it linked to future tool responses
   * @param functionName required.
   * @param expectedArgsFmt 'incr_str' | 'json_object' - 'incr_str' for incremental string, 'json_object' for JSON object
   * @param args must be undefined, or match the expected Args Format
   */
  startFunctionCallInvocation(id: string | null, functionName: string, expectedArgsFmt: 'incr_str' | 'json_object', args: string | object | null): void;

  /** Appends data to a FC part [throttled] */
  appendFunctionCallInvocationArgs(id: string | null, argsJsonChunk: string): void;

  /** Creates a CE request part, flushing the previous one if needed, and completes it */
  addCodeExecutionInvocation(id: string | null, language: string, code: string, author: 'gemini_auto_inline' | 'code_interpreter'): void;

  /** Creates a CE result part, flushing the previous one if needed, and completes it */
  addCodeExecutionResponse(id: string | null, error: boolean | string, result: string, executor: 'gemini_auto_inline' | 'code_interpreter', environment: 'upstream'): void;

  /** Adds a URL citation part */
  appendUrlCitation(title: string, url: string, citationNumber?: number, startIndex?: number, endIndex?: number, textSnippet?: string, pubTs?: number): void;

  // Special //

  /** Sends control particles right away, such as retry-reset control particles */
  sendControl(cgCOp: AixWire_Particles.ChatControlOp, flushQueue?: boolean): void;

  /** Sends a void placeholder particle - temporary status that gets wiped when real content arrives */
  sendVoidPlaceholder(mot: 'search-web' | 'gen-image' | 'code-exec', text: string): void;

  /**
   * Sends vendor-specific state modifier for the last emitted part.
   * Used to attach opaque protocol state (e.g., Gemini thoughtSignature) without polluting core part schemas.
   */
  sendSetVendorState(vendor: string, state: unknown): void;

  // Non-parts data //

  /** Communicates the model name to the client */
  setModelName(modelName: string): void;

  /** Communicates the provider name to the client (e.g., OpenRouter provider routing) */
  setProviderInfraLabel(label: string): void;

  /** Communicates the upstream response handle, for remote control/resumability */
  setUpstreamHandle(handle: string, type: 'oai-responses'): void;

  /** Update the metrics, sent twice (after the first call, and then at the end of the transmission) */
  updateMetrics(update: Partial<AixWire_Particles.CGSelectMetrics>): void;

}
