import type { Hono } from 'hono';
import type { CryptoProvider } from '@shade/core';
import { createInboxRoutes, type InboxRoutesOptions } from './routes.js';
import { MemoryInboxStore } from './memory-store.js';
import type { InboxStore } from './store.js';
import { InboxServerEvents } from './events.js';

export { createInboxRoutes } from './routes.js';
export type { InboxRoutesOptions } from './routes.js';
export { MemoryInboxStore } from './memory-store.js';
export type { InboxStore } from './store.js';
export {
  InboxServerEvents,
  shortHash as inboxShortHash,
} from './events.js';
export type {
  InboxServerEvent,
  InboxServerEventName,
  InboxServerEventMap,
  InboxServerEventListener,
} from './events.js';
export { InboxPruneTask } from './cleanup.js';
export {
  computeMsgId,
  isValidMsgId,
  constantTimeStringEqual,
} from './msg-id.js';
export {
  DEFAULT_INBOX_QUOTA,
  clampTtl,
} from './quota.js';
export type { InboxQuotaConfig } from './quota.js';
export { createBridgeRoutes } from './bridge.js';
export type { BridgeRoutesOptions, BridgeKind } from './bridge.js';
export { PresenceTracker } from './presence.js';
export type { TrackedBridgeKind } from './presence.js';

/**
 * Create a standalone Shade Inbox Server.
 *
 *   const crypto = new SubtleCryptoProvider();
 *   const inbox = createInboxServer({ crypto });
 *   export default { port: 3901, fetch: inbox.fetch };
 *
 * Or compose into an existing Hono app:
 *   const app = new Hono();
 *   app.route('/', createInboxServer({ crypto }));
 */
export function createInboxServer(options: {
  crypto: CryptoProvider;
  store?: InboxStore;
  disableRateLimit?: boolean;
  events?: InboxServerEvents;
} & Pick<InboxRoutesOptions, 'observability' | 'quota'>): Hono {
  const store = options.store ?? new MemoryInboxStore();
  const routesOptions: InboxRoutesOptions = {};
  if (options.disableRateLimit !== undefined) routesOptions.disableRateLimit = options.disableRateLimit;
  if (options.events !== undefined) routesOptions.events = options.events;
  if (options.observability !== undefined) routesOptions.observability = options.observability;
  if (options.quota !== undefined) routesOptions.quota = options.quota;
  return createInboxRoutes(store, options.crypto, routesOptions);
}
