import type { WireProfileName } from './topics';

/**
 * Matrix Envelope Types
 *
 * CANONICAL SOURCE: packages/matrix-transport/src/interfaces/MxEnvelopeV1.ts
 *
 * This file maintains federation-specific types that extend/wrap the canonical
 * MxEnvelopeV1 format. The types here are kept in sync with matrix-transport.
 *
 * Migration path:
 * - New code should use matrix-transport MxEnvelopeV1 when possible
 * - Legacy code can continue using CrossRealmEnvelopeLegacy/ReplyEnvelopeLegacy
 * - The envelope_codec.ts provides translation between formats
 */

// ===== Legacy Matrix-3 envelopes (deprecated, use MxEnvelopeV1) =====

export interface CrossRealmEnvelopeLegacy {
  // Routing — canonical names are toRoot/fromRoot
  toRoot: string;
  toPath: string;

  fromRoot: string;
  replyTo: string;

  correlationId: string;
  idempotencyKey?: string;

  body: unknown;

  timestamp?: string;
  ttlMs?: number;
  traceId?: string;

  /** OPTIONAL extension to support events without switching profile */
  type?: 'request' | 'event';

  // --- Deprecated aliases (wire compat) ---
  /** @deprecated Use toRoot */
  toRealm?: string;
  /** @deprecated Use fromRoot */
  fromRealm?: string;
}

export interface ReplyEnvelopeLegacy {
  toRoot: string;
  toPath: string;
  fromRoot: string;
  correlationId: string;

  body: unknown;
  ok: boolean;
  error?: {
    code: string;
    message: string;
    details?: unknown;
  };

  timestamp?: string;
  traceId?: string;

  /** OPTIONAL explicit discriminator */
  type?: 'reply';

  // --- Deprecated aliases (wire compat) ---
  /** @deprecated Use toRoot */
  toRealm?: string;
  /** @deprecated Use fromRoot */
  fromRealm?: string;
}

// ===== MXENV/1 envelope (canonical - synced with matrix-transport) =====
//
// These types mirror packages/matrix-transport/src/interfaces/MxEnvelopeV1.ts
// Keep in sync when making changes!

export type MxMsgType = 'Cmd' | 'Evt' | 'Result' | 'Sub' | 'Unsub' | 'Nack';

export interface MxAddress {
  root: string;
  path: string;
  /** @deprecated Use root instead */
  realm?: string;
}

export interface MxPrincipal {
  kind: 'anon' | 'jwt' | 'service';
  iss?: string;
  sub?: string;
  aud?: string[];
  scopes?: string[];
}

export interface MxAuth {
  bearer?: string;
  capability?: string;
}

export interface MxEnvelopeV1 {
  ver: 1;
  msgType: MxMsgType;
  msgId: string;
  timestamp: string;

  correlationId?: string;

  // Routing
  to: MxAddress;
  from: MxAddress;
  replyTo?: MxAddress;

  // Federation (hop-based TTL for MXROUTE)
  ttl?: number;

  // Security
  principal?: MxPrincipal;
  auth?: MxAuth;

  // Distributed Tracing (OpenTelemetry compatible)
  traceId?: string;
  spanId?: string;
  parentSpanId?: string;

  // Payload
  body: unknown;

  // Result fields
  ok?: boolean;
  error?: {
    code: string;
    message: string;
    details?: unknown;
  };
}

// ===== Tagged decode result =====

export type TaggedEnvelope =
  | { profile: 'mxenv1'; envelope: MxEnvelopeV1 }
  | { profile: 'matrix3'; kind: 'request'; envelope: CrossRealmEnvelopeLegacy }
  | { profile: 'matrix3'; kind: 'reply'; envelope: ReplyEnvelopeLegacy };

export interface WireContext {
  profile: WireProfileName;
}
