import express from 'express';
import { Engine, LookupService, TopicManager, Advertiser } from '@bsv/overlay';
import { ChainTracker, Broadcaster, OverlayBroadcastFacilitator, WalletInterface } from '@bsv/sdk';
import Knex from 'knex';
import { MongoClient, Db } from 'mongodb';
import { type UIConfig } from './makeUserInterface.js';
import { BanService } from './BanService.js';
/**
 * Knex database migration.
 */
interface Migration {
    name?: string;
    up: (knex: Knex.Knex) => Promise<void>;
    down?: (knex: Knex.Knex) => Promise<void>;
}
/**
 * Configuration options that map to Engine constructor parameters.
 */
export interface EngineConfig {
    chainTracker?: ChainTracker | 'scripts only';
    shipTrackers?: string[];
    slapTrackers?: string[];
    broadcaster?: Broadcaster;
    advertiser?: Advertiser;
    syncConfiguration?: Record<string, string[] | 'SHIP' | false>;
    logTime?: boolean;
    logPrefix?: string;
    throwOnBroadcastFailure?: boolean;
    overlayBroadcastFacilitator?: OverlayBroadcastFacilitator;
    suppressDefaultSyncAdvertisements?: boolean;
    topicAnchorHeaderResolver?: TopicAnchorHeaderResolver;
    enableBASMSync?: boolean;
    unprovenEvictionBlocks?: number;
    reorgStreamUrl?: string;
    reorgScanDepth?: number;
    unprovenMaintenanceIntervalMs?: number;
}
export type HealthStatus = 'ok' | 'degraded' | 'error';
export interface HealthCheckResult {
    name: string;
    scope: 'live' | 'ready';
    status: HealthStatus;
    critical: boolean;
    message?: string;
    details?: Record<string, any>;
    durationMs: number;
}
export type HealthCheckHandler = () => Promise<Omit<HealthCheckResult, 'name' | 'scope' | 'critical' | 'durationMs'> | void> | Omit<HealthCheckResult, 'name' | 'scope' | 'critical' | 'durationMs'> | void;
export interface HealthCheckDefinition {
    name: string;
    scope?: 'live' | 'ready';
    critical?: boolean;
    handler: HealthCheckHandler;
}
export interface HealthConfig {
    includeDetails: boolean;
    timeoutMs: number;
    contextProvider?: () => Promise<Record<string, any> | undefined> | Record<string, any> | undefined;
}
export interface HealthReport {
    status: HealthStatus;
    live: boolean;
    ready: boolean;
    service: {
        name: string;
        advertisableFQDN: string;
        port: number;
        network: 'main' | 'test';
        startedAt?: string;
        uptimeMs: number;
        topicManagerCount: number;
        lookupServiceCount: number;
    };
    checks: HealthCheckResult[];
    context?: Record<string, any>;
}
export type TopicAnchorHeaderResolver = (blockHeight: number) => Promise<{
    blockHeight: number;
    blockHash: string;
    merkleRoot?: string;
} | undefined>;
/**
 * OverlayExpress class provides an Express-based server for hosting Overlay Services.
 * It allows configuration of various components like databases, topic managers, and lookup services.
 * It encapsulates an Express application and provides methods to start the server.
 */
export default class OverlayExpress {
    name: string;
    privateKey: string;
    advertisableFQDN: string;
    app: express.Application;
    port: number;
    logger: typeof console;
    knex?: Knex.Knex;
    migrationsToRun: Migration[];
    mongoDb?: Db;
    mongoClient?: MongoClient;
    network: 'main' | 'test';
    chainTracker: ChainTracker | 'scripts only';
    engine?: Engine;
    managers: Record<string, TopicManager>;
    services: Record<string, LookupService>;
    enableGASPSync: boolean;
    enableBASMSync: boolean;
    unprovenEvictionBlocks: number;
    basmBlockPollIntervalMs: number;
    private basmBlockPollTimer?;
    unprovenMaintenanceIntervalMs: number;
    private unprovenMaintenanceTimer?;
    reorgStreamUrl?: string;
    reorgScanDepth: number;
    private reorgAdapter?;
    topicAnchorHeaderResolver?: TopicAnchorHeaderResolver;
    arcApiKey: string | undefined;
    arcCallbackToken: string | undefined;
    arcadeUrl: string | undefined;
    arcadeApiKey: string | undefined;
    arcadeDeploymentId: string | undefined;
    arcadeChaintracksApiPrefix: string;
    private arcadeProvider?;
    verboseRequestLogging: boolean;
    webUIConfig: UIConfig;
    engineConfig: EngineConfig;
    private readonly adminToken;
    janitorConfig: {
        requestTimeoutMs: number;
        hostDownRevokeScore: number;
        autoBanOnRemoval: boolean;
    };
    banService?: BanService;
    adminIdentityKey?: string;
    serverWallet?: WalletInterface;
    private startTime?;
    healthConfig: HealthConfig;
    healthChecks: HealthCheckDefinition[];
    isListening: boolean;
    /**
     * Constructs an instance of OverlayExpress.
     * @param name - The name of the service
     * @param privateKey - Private key used for signing advertisements
     * @param advertisableFQDN - The fully qualified domain name where this service is available. Does not include "https://".
     * @param adminToken - Optional. An administrative Bearer token used to protect admin routes.
     *                     If not provided, a random token will be generated at runtime.
     */
    constructor(name: string, privateKey: string, advertisableFQDN: string, adminToken?: string);
    /**
     * Returns the current admin token in case you need to programmatically retrieve or display it.
     */
    getAdminToken(): string;
    /**
     * Configures the port on which the server will listen.
     * @param port - The port number
     */
    configurePort(port: number): void;
    /**
     * Configures the web user interface
     * @param config - Web UI configuration options
     */
    configureWebUI(config: UIConfig): void;
    /**
     * Configures the janitor service parameters
     * @param config - Janitor configuration options
     *   - requestTimeoutMs: Timeout for health check requests (default: 10000ms)
     *   - hostDownRevokeScore: Number of consecutive failures before deleting output (default: 3)
     *   - autoBanOnRemoval: Whether to auto-ban domains when removed by janitor (default: true)
     */
    configureJanitor(config: Partial<typeof this.janitorConfig>): void;
    /**
     * Configures health-report behavior.
     */
    configureHealth(config: Partial<HealthConfig>): void;
    /**
     * Registers an application-specific health check.
     */
    registerHealthCheck(definition: HealthCheckDefinition): void;
    /**
     * Configures the admin identity key for wallet-based admin detection.
     * When set, the frontend can compare the user's wallet identity key against this
     * to determine whether to show the admin dashboard.
     *
     * @param identityKey - The hex-encoded public key of the admin
     */
    configureAdminIdentityKey(identityKey: string): void;
    /**
     * Configures the logger to be used by the server.
     * @param logger - A logger object (e.g., console)
     */
    configureLogger(logger: typeof console): void;
    /**
     * Configures the BSV Blockchain network to be used ('main' or 'test').
     * By default, it re-initializes chainTracker as a WhatsOnChain for that network.
     * @param network - The network ('main' or 'test')
     */
    configureNetwork(network: 'main' | 'test'): void;
    /**
     * Configures the ChainTracker to be used.
     * If 'scripts only' is used, it implies no full SPV chain tracking in the Engine.
     * @param chainTracker - An instance of ChainTracker or 'scripts only'
     */
    configureChainTracker(chainTracker?: ChainTracker | 'scripts only'): void;
    /**
     * Configures the ARC API key.
     * @param apiKey - The ARC API key
     */
    configureArcApiKey(apiKey: string): void;
    /**
     * Configures the ARC callback token expected by /arc-ingest.
     * @param token - The token ARC should present when posting callback notifications.
     */
    configureArcCallbackToken(token: string): void;
    /**
     * Configures Arcade for first-choice transaction propagation and proof lookup.
     */
    configureArcade(url: string, config?: {
        apiKey?: string;
        deploymentId?: string;
        chaintracksApiPrefix?: string;
    }): void;
    /**
     * Configures a go-chaintracks compatible service for header validation and
     * BASM reorg streaming. Arcade exposes this at `/chaintracks/v2`.
     */
    configureChaintracks(url: string, config?: {
        apiPrefix?: string;
        reorgStream?: boolean;
        scanDepth?: number;
    }): void;
    /**
     * Enables or disables GASP synchronization (high-level setting).
     * This is a broad toggle that can be overridden or customized through syncConfiguration.
     * @param enable - true to enable, false to disable
     */
    configureEnableGASPSync(enable: boolean): void;
    /**
     * Enables or disables BRC-136 BASM synchronization.
     * BASM is opt-in because it requires direct proofs and block hash resolution.
     */
    configureEnableBASMSync(enable: boolean): void;
    /**
     * Configures the block header resolver used to derive BASM block hashes.
     */
    configureTopicAnchorHeaderResolver(resolver: TopicAnchorHeaderResolver): void;
    /**
     * Configures the go-chaintracks (Arcade) reorg SSE stream used to reconcile
     * BASM anchors with blockchain reorganizations in real time.
     * @param url - The reorg stream URL, e.g. `https://arcade.example/v2/reorg/stream`.
     * @param scanDepth - Optional revalidation-sweep depth in blocks (default 3).
     */
    configureReorgStream(url: string, scanDepth?: number): void;
    /**
     * Configures the opt-in unproven state eviction threshold.
     */
    configureUnprovenEviction(config: {
        thresholdBlocks?: number;
    }): void;
    /**
     * Configures periodic unproven maintenance. Each run first tries configured
     * proof providers, then evicts rows that are still unproven past the threshold.
     */
    configureUnprovenMaintenance(config: {
        intervalMs?: number;
        thresholdBlocks?: number;
    }): void;
    /**
     * Configures how often the BASM anchor chain is extended with empty anchors to
     * follow the chain tip. Set to 0 to disable periodic polling.
     */
    configureBASMBlockPollInterval(intervalMs: number): void;
    /**
     * Enables or disables verbose request logging.
     * @param enable - true to enable, false to disable
     */
    configureVerboseRequestLogging(enable: boolean): void;
    /**
     * Configure Knex (SQL) database connection.
     * @param config - Knex configuration object, or a MySQL connection string loaded from configuration.
     */
    configureKnex(config: Knex.Knex.Config | string): Promise<void>;
    /**
     * Configures the MongoDB database connection.
     * Also initializes the BanService for persistent ban tracking.
     * @param connectionString - MongoDB connection string
     */
    configureMongo(connectionString: string): Promise<void>;
    /**
     * Configures a Topic Manager.
     * @param name - The name of the Topic Manager
     * @param manager - An instance of TopicManager
     */
    configureTopicManager(name: string, manager: TopicManager): void;
    /**
     * Configures a Lookup Service.
     * @param name - The name of the Lookup Service
     * @param service - An instance of LookupService
     */
    configureLookupService(name: string, service: LookupService): void;
    /**
     * Configures a Lookup Service using Knex (SQL) database.
     * @param name - The name of the Lookup Service
     * @param serviceFactory - A factory function that creates a LookupService instance using Knex
     */
    configureLookupServiceWithKnex(name: string, serviceFactory: (knex: Knex.Knex) => {
        service: LookupService;
        migrations: Migration[];
    }): void;
    /**
     * Configures a Lookup Service using MongoDB.
     * @param name - The name of the Lookup Service
     * @param serviceFactory - A factory function that creates a LookupService instance using MongoDB
     */
    configureLookupServiceWithMongo(name: string, serviceFactory: (mongoDb: Db) => LookupService): void;
    /**
     * Advanced configuration method for setting or overriding any
     * Engine constructor parameters via an EngineConfig object.
     *
     * Example usage:
     *   configureEngineParams({
     *     logTime: true,
     *     throwOnBroadcastFailure: true,
     *     overlayBroadcastFacilitator: new MyCustomFacilitator()
     *   })
     *
     * These fields will be respected when we finally build/configure the Engine
     * in the `configureEngine()` method below.
     */
    configureEngineParams(params: EngineConfig): void;
    /**
     * Configures the Overlay Engine itself.
     * By default, auto-configures SHIP and SLAP unless autoConfigureShipSlap = false
     * Then it merges in any advanced engine config from `this.engineConfig`.
     *
     * When a BanService is available (from configureMongo), auto-configured SHIP
     * and SLAP managers, discovery storage, and lookup services are wrapped so
     * banned outputs are not admitted or indexed.
     *
     * @param autoConfigureShipSlap - Whether to auto-configure SHIP and SLAP services (default: true)
     */
    configureEngine(autoConfigureShipSlap?: boolean): Promise<void>;
    /** Wrap SHIP/SLAP managers and services with ban-aware filters if BanService is configured. */
    private wrapBanAwareServices;
    /** Build the sync config based on enableGASPSync and engineConfig. */
    private buildSyncConfig;
    /** Build the configured transaction propagation provider chain. */
    private buildBroadcaster;
    private ensureArcadeProvider;
    private fetchArcadeProof;
    private fetchConfiguredMerkleProof;
    /** Build the BASM block header resolver. */
    private buildTopicAnchorHeaderResolver;
    /** Resolve the SLAP trackers from config or network defaults. */
    private resolveSlapTrackers;
    /** Build the WalletAdvertiser (or use user-provided one). */
    private buildAdvertiser;
    /** Initialize the server wallet for BSV mutual authentication. */
    private initServerWallet;
    /**
     * Ensures that Knex is configured and returns it.
     * @throws Error if Knex is not configured
     */
    private ensureKnex;
    /**
     * Ensures that MongoDB is configured and returns it.
     * @throws Error if MongoDB is not configured
     */
    private ensureMongo;
    /**
     * Ensures that the Overlay Engine is configured and returns it.
     * @throws Error if the Engine is not configured
     */
    private ensureEngine;
    /**
     * Creates a JanitorService instance with current configuration.
     */
    private createJanitor;
    /** Ban a domain and remove all its SHIP/SLAP records from MongoDB. */
    private handleBanDomain;
    /** Parse outpoint string, ban it, and evict it from all lookup services. */
    private handleBanOutpoint;
    /** Evict an output from a specific service or all services (silent per-service errors). */
    private evictFromServices;
    /** Look up the domain of an outpoint from SHIP or SLAP records. */
    private lookupDomainForOutpoint;
    /** Ban a domain and delete all SHIP/SLAP records for it. */
    private banDomainAndRemoveRecords;
    private runHealthCheck;
    private collectHealthReport;
    /**
     * Renders a request or response body for verbose logging, truncating overly long payloads.
     */
    private formatBodyForLog;
    /**
     * Installs middleware that verbosely logs incoming requests and outgoing responses.
     */
    private setupVerboseRequestLogging;
    /**
     * Starts the Express server.
     * Sets up routes and begins listening on the configured port.
     */
    start(): Promise<void>;
    /**
     * Runs the post-listen startup work: advertiser init, advertisement sync,
     * and the optional GASP/BASM background syncs.
     */
    private runStartupSync;
    /** Attempt a GASP sync at startup when enabled. */
    private runGaspStartupSync;
    /** Attempt a BASM sync at startup when enabled, then begin tip-following. */
    private runBasmStartupSync;
    /** Poll for new blocks to advance anchor chains and detect reorgs. */
    private startBASMBlockPolling;
    /** Real-time reorg reconciliation via the go-chaintracks (Arcade) reorg SSE. */
    private startBASMReorgStream;
    /** Extend every topic's BASM anchor chain to the current chain tip. */
    private advanceBASMAnchorChains;
    /** Revalidate recent BASM anchors against the chain tracker, reconciling any reorg. */
    private revalidateBASMAnchors;
    private startUnprovenMaintenance;
}
export {};
//# sourceMappingURL=OverlayExpress.d.ts.map