import { TracerProvider } from "@opentelemetry/api";
import { ActorCallbackSetters, ActorDispatcher, ActorKeyPair, CollectionCallbackSetters, CollectionDispatcher, Context, Federation, FederationFetchOptions, FederationStartQueueOptions, InboxListenerSetters, Message, NodeInfoDispatcher, ObjectCallbackSetters, ObjectDispatcher, ParseUriResult, RequestContext, RouteActivityOptions, SendActivityOptions, SendActivityOptionsForCollection, SenderKeyPair } from "@fedify/fedify/federation";
import { Activity, Actor, Collection, Hashtag, LookupObjectOptions, Object as Object$1, Recipient, TraverseCollectionOptions } from "@fedify/fedify/vocab";
import { ResourceDescriptor } from "@fedify/fedify/webfinger";
import { JsonValue, NodeInfo } from "@fedify/fedify/nodeinfo";
import { DocumentLoader } from "@fedify/fedify/runtime";

//#region mock.d.ts

/**
 * Represents a sent activity with metadata about how it was sent.
 * @since 1.8.0
 */
interface SentActivity {
  /** Whether the activity was queued or sent immediately. */
  queued: boolean;
  /** Which queue was used (if queued). */
  queue?: "inbox" | "outbox" | "fanout";
  /** The activity that was sent. */
  activity: Activity;
  /** The order in which the activity was sent (auto-incrementing counter). */
  sentOrder: number;
}
/**
 * A mock implementation of the {@link Federation} interface for unit testing.
 * This class provides a way to test Fedify applications without needing
 * a real federation setup.
 *
 * @example
 * ```typescript
 * import { Create } from "@fedify/fedify/vocab";
 * import { MockFederation } from "@fedify/testing";
 *
 * // Create a mock federation with contextData
 * const federation = new MockFederation<{ userId: string }>({
 *   contextData: { userId: "test-user" }
 * });
 *
 * // Set up inbox listeners
 * federation
 *   .setInboxListeners("/users/{identifier}/inbox")
 *   .on(Create, async (ctx, activity) => {
 *     console.log("Received:", activity);
 *   });
 *
 * // Simulate receiving an activity
 * const createActivity = new Create({
 *   id: new URL("https://example.com/create/1"),
 *   actor: new URL("https://example.com/users/alice")
 * });
 * await federation.receiveActivity(createActivity);
 * ```
 *
 * @typeParam TContextData The context data to pass to the {@link Context}.
 * @since 1.8.0
 */
declare class MockFederation<TContextData> implements Federation<TContextData> {
  private options;
  sentActivities: SentActivity[];
  queueStarted: boolean;
  private activeQueues;
  sentCounter: number;
  private nodeInfoDispatcher?;
  private actorDispatchers;
  actorPath?: string;
  inboxPath?: string;
  outboxPath?: string;
  followingPath?: string;
  followersPath?: string;
  likedPath?: string;
  featuredPath?: string;
  featuredTagsPath?: string;
  nodeInfoPath?: string;
  sharedInboxPath?: string;
  objectPaths: Map<string, string>;
  private objectDispatchers;
  private inboxDispatcher?;
  private outboxDispatcher?;
  private followingDispatcher?;
  private followersDispatcher?;
  private likedDispatcher?;
  private featuredDispatcher?;
  private featuredTagsDispatcher?;
  private inboxListeners;
  private contextData?;
  private receivedActivities;
  constructor(options?: {
    contextData?: TContextData;
    origin?: string;
    tracerProvider?: TracerProvider;
  });
  setNodeInfoDispatcher(path: string, dispatcher: NodeInfoDispatcher<TContextData>): void;
  setActorDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: ActorDispatcher<TContextData>): ActorCallbackSetters<TContextData>;
  setObjectDispatcher<TObject extends Object$1, TParam extends string>(cls: (new (...args: any[]) => TObject) & {
    typeId: URL;
  }, path: string, dispatcher: ObjectDispatcher<TContextData, TObject, TParam>): ObjectCallbackSetters<TContextData, TObject, TParam>;
  setInboxDispatcher(_path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
  setOutboxDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
  setFollowingDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Actor | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
  setFollowersDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Recipient, Context<TContextData>, TContextData, URL>): CollectionCallbackSetters<Context<TContextData>, TContextData, URL>;
  setLikedDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Object$1 | URL, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
  setFeaturedDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Object$1, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
  setFeaturedTagsDispatcher(path: `${string}{identifier}${string}` | `${string}{handle}${string}`, dispatcher: CollectionDispatcher<Hashtag, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
  setInboxListeners(inboxPath: `${string}{identifier}${string}` | `${string}{handle}${string}`, sharedInboxPath?: string): InboxListenerSetters<TContextData>;
  startQueue(contextData: TContextData, options?: FederationStartQueueOptions): Promise<void>;
  processQueuedTask(contextData: TContextData, _message: Message): Promise<void>;
  createContext(baseUrl: URL, contextData: TContextData): Context<TContextData>;
  createContext(request: Request, contextData: TContextData): RequestContext<TContextData>;
  fetch(request: Request, options: FederationFetchOptions<TContextData>): Promise<Response>;
  /**
   * Simulates receiving an activity. This method is specific to the mock
   * implementation and is used for testing purposes.
   *
   * @param activity The activity to receive.
   * @returns A promise that resolves when the activity has been processed.
   * @since 1.8.0
   */
  receiveActivity(activity: Activity): Promise<void>;
  /**
   * Clears all sent activities from the mock federation.
   * This method is specific to the mock implementation and is used for
   * testing purposes.
   *
   * @since 1.8.0
   */
  reset(): void;
}
/**
 * A mock implementation of the {@link Context} interface for unit testing.
 * This class provides a way to test Fedify applications without needing
 * a real federation context.
 *
 * @example
 * ```typescript
 * import { Person, Create } from "@fedify/fedify/vocab";
 * import { MockContext, MockFederation } from "@fedify/testing";
 *
 * // Create a mock context
 * const mockFederation = new MockFederation<{ userId: string }>();
 * const context = new MockContext({
 *   url: new URL("https://example.com"),
 *   data: { userId: "test-user" },
 *   federation: mockFederation
 * });
 *
 * // Send an activity
 * const recipient = new Person({ id: new URL("https://example.com/users/bob") });
 * const activity = new Create({
 *   id: new URL("https://example.com/create/1"),
 *   actor: new URL("https://example.com/users/alice")
 * });
 * await context.sendActivity(
 *   { identifier: "alice" },
 *   recipient,
 *   activity
 * );
 *
 * // Check sent activities
 * const sent = context.getSentActivities();
 * console.log(sent[0].activity);
 * ```
 *
 * @typeParam TContextData The context data to pass to the {@link Context}.
 * @since 1.8.0
 */
declare class MockContext<TContextData> implements Context<TContextData> {
  readonly origin: string;
  readonly canonicalOrigin: string;
  readonly host: string;
  readonly hostname: string;
  readonly data: TContextData;
  readonly federation: Federation<TContextData>;
  readonly documentLoader: DocumentLoader;
  readonly contextLoader: DocumentLoader;
  readonly tracerProvider: TracerProvider;
  private sentActivities;
  constructor(options: {
    url?: URL;
    data: TContextData;
    federation: Federation<TContextData>;
    documentLoader?: DocumentLoader;
    contextLoader?: DocumentLoader;
    tracerProvider?: TracerProvider;
  });
  clone(data: TContextData): Context<TContextData>;
  getNodeInfoUri(): URL;
  getActorUri(identifier: string): URL;
  getObjectUri<TObject extends Object$1>(cls: (new (...args: any[]) => TObject) & {
    typeId: URL;
  }, values: Record<string, string>): URL;
  getOutboxUri(identifier: string): URL;
  getInboxUri(identifier: string): URL;
  getInboxUri(): URL;
  getFollowingUri(identifier: string): URL;
  getFollowersUri(identifier: string): URL;
  getLikedUri(identifier: string): URL;
  getFeaturedUri(identifier: string): URL;
  getFeaturedTagsUri(identifier: string): URL;
  parseUri(uri: URL): ParseUriResult | null;
  getActorKeyPairs(_identifier: string): Promise<ActorKeyPair[]>;
  getDocumentLoader(params: {
    handle: string;
  } | {
    identifier: string;
  }): Promise<DocumentLoader>;
  getDocumentLoader(params: {
    keyId: URL;
    privateKey: CryptoKey;
  }): DocumentLoader;
  lookupObject(_uri: URL | string, _options?: LookupObjectOptions): Promise<Object$1 | null>;
  traverseCollection<TItem, TContext extends Context<TContextData>>(_collection: Collection | URL | null, _options?: TraverseCollectionOptions): AsyncIterable<TItem>;
  lookupNodeInfo(url: URL | string, options?: {
    parse?: "strict" | "best-effort";
  } & any): Promise<NodeInfo | undefined>;
  lookupNodeInfo(url: URL | string, options?: {
    parse: "none";
  } & any): Promise<JsonValue | undefined>;
  lookupWebFinger(_resource: URL | `acct:${string}@${string}` | string, _options?: any): Promise<ResourceDescriptor | null>;
  sendActivity(sender: SenderKeyPair | SenderKeyPair[] | {
    identifier: string;
  } | {
    username: string;
  } | {
    handle: string;
  }, recipients: Recipient | Recipient[], activity: Activity, options?: SendActivityOptions): Promise<void>;
  sendActivity(sender: {
    identifier: string;
  } | {
    username: string;
  } | {
    handle: string;
  }, recipients: "followers", activity: Activity, options?: SendActivityOptionsForCollection): Promise<void>;
  sendActivity(sender: SenderKeyPair | SenderKeyPair[] | {
    identifier: string;
  } | {
    username: string;
  } | {
    handle: string;
  }, recipients: Recipient | Recipient[], activity: Activity, options?: SendActivityOptions): Promise<void>;
  sendActivity(sender: {
    identifier: string;
  } | {
    username: string;
  } | {
    handle: string;
  }, recipients: "followers", activity: Activity, options?: SendActivityOptionsForCollection): Promise<void>;
  routeActivity(_recipient: string | null, _activity: Activity, _options?: RouteActivityOptions): Promise<boolean>;
  /**
   * Gets all activities that have been sent through this mock context.
   * This method is specific to the mock implementation and is used for
   * testing purposes.
   *
   * @returns An array of sent activity records.
   */
  getSentActivities(): Array<{
    sender: SenderKeyPair | SenderKeyPair[] | {
      identifier: string;
    } | {
      username: string;
    } | {
      handle: string;
    };
    recipients: Recipient | Recipient[] | "followers";
    activity: Activity;
  }>;
  /**
   * Clears all sent activities from the mock context.
   * This method is specific to the mock implementation and is used for
   * testing purposes.
   */
  reset(): void;
}
//#endregion
export { MockContext, MockFederation, SentActivity };