// src/transport/WireCodecTransport.ts
//
// Transport decorator — now a pass-through (DNS hierarchical addressing).
// Kept as a shell for migration safety; will be removed in a follow-up.

import type { Transport, MessageHandler, TransportMeta } from '@open-matrix/federation';

interface ITransportWithInternals {
  readonly root?: string;
  readonly realm?: string; // backward compat
  getUnderlyingClient(): unknown;
  disconnect(): Promise<void>;
  flushSubscriptions?(): Promise<void>;
}

export interface IWireCodecTransportOptions {
  /** Globally unique root identity (e.g., 'com.nimbletec.richard.santomauro') */
  root?: string;
  /** @deprecated Use `root`. */
  realm?: string;
  /** Enable verbose debug logging */
  debug?: boolean;
}

/**
 * Transport decorator — now a pass-through identity function.
 *
 * With DNS hierarchical addressing, the NATS subject IS the fully
 * qualified address ({root}.{mount}.$facet). No encoding needed.
 * Kept as a shell for migration safety; will be removed in a follow-up.
 */
export class WireCodecTransport implements Transport {
  private readonly _inner: Transport & Partial<ITransportWithInternals>;
  private readonly _root: string;
  private readonly _debug: boolean;

  constructor(inner: Transport, options: IWireCodecTransportOptions) {
    this._inner = inner as Transport & Partial<ITransportWithInternals>;
    this._root = options.root ?? options.realm ?? '';
    this._debug = options.debug ?? false;
  }

  /** The root this transport encodes for. Used by RequestReply for cross-root detection. */
  get root(): string {
    return this._inner.root ?? this._inner.realm ?? this._root;
  }

  /** @deprecated Use `root`. */
  get realm(): string {
    return this.root;
  }

  /**
   * Delegate underlying-client access through the wire codec layer.
   */
  getUnderlyingClient(): unknown {
    if (typeof this._inner.getUnderlyingClient === 'function') {
      return this._inner.getUnderlyingClient();
    }
    return this._inner;
  }

  /**
   * Delegate disconnect through the wire codec layer.
   */
  async disconnect(): Promise<void> {
    if (typeof this._inner.disconnect === 'function') {
      await this._inner.disconnect();
    }
  }

  /**
   * Identity pass-through. With DNS hierarchical addressing, the NATS subject
   * IS the fully qualified address — no encoding layer needed.
   * Kept as shell for migration safety; will be deleted in follow-up.
   */
  private _encode(localTopic: string): string {
    return localTopic;
  }

  /**
   * Identity pass-through. See _encode().
   */
  private _decode(wireTopic: string): string {
    return wireTopic;
  }

  publish(topic: string, payload: string, meta?: TransportMeta): void {
    const wireTopic = this._encode(topic);
    if (this._debug) {
      // eslint-disable-next-line no-console -- kernel wire codec debug diagnostics are opt-in and have no actor context
      console.log(`[WireCodec] → ${topic} → ${wireTopic}`);
    }
    this._inner.publish(wireTopic, payload, meta);
  }

  subscribe(topic: string, handler: MessageHandler): () => void {
    const wireTopic = this._encode(topic);
    if (this._debug) {
      // eslint-disable-next-line no-console -- kernel wire codec debug diagnostics are opt-in and have no actor context
      console.log(`[WireCodec] SUB ${topic} → ${wireTopic}`);
    }

    // Wrap handler to decode wire topic back to local
    const wrappedHandler: MessageHandler = (receivedWireTopic, payload, meta) => {
      const localTopic = this._decode(receivedWireTopic);
      handler(localTopic, payload, meta);
    };

    return this._inner.subscribe(wireTopic, wrappedHandler);
  }

  /**
   * Access to flushSubscriptions() if the inner transport supports it.
   */
  async flushSubscriptions(): Promise<void> {
    if (typeof this._inner.flushSubscriptions === 'function') {
      await this._inner.flushSubscriptions();
    }
  }
}
