import { EnsRainbow } from '@ensnode/ensrainbow-sdk';
import { MiddlewareHandler } from 'hono';
import { ReadonlyDrizzle } from 'ponder';
import { PublicClient } from 'viem';
import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';

/**
 * Basic information about a block.
 */
interface BlockInfo {
    /** block number */
    number: number;
    /** block unix timestamp */
    timestamp: number;
}
/**
 * Network indexing status for a chain.
 */
interface NetworkIndexingStatus {
    /**
     * First block required to be indexed during the historical sync.
     */
    firstBlockToIndex: BlockInfo;
    /**
     * Latest block synced into indexer's RPC cache.
     */
    lastSyncedBlock: BlockInfo | null;
    /**
     * Last block processed & indexed by the indexer.
     */
    lastIndexedBlock: BlockInfo | null;
    /**
     * Latest safe block available on the chain.
     */
    latestSafeBlock: BlockInfo;
}

type PonderEnvVarsInfo = Record<string, unknown>;
interface PonderMetadataMiddlewareOptions<AppInfo, EnvVars extends PonderEnvVarsInfo> {
    /** Database access object (readonly Drizzle) */
    db: ReadonlyDrizzle<Record<string, unknown>>;
    /** Application info */
    app: AppInfo;
    /** Environment settings info */
    env: EnvVars;
    /** Query methods */
    query: {
        /** Fetches prometheus metrics for Ponder application */
        prometheusMetrics(): Promise<string>;
        /** Fetches the first block do be indexed for a requested chain ID */
        firstBlockToIndexByChainId(chainId: number, publicClient: PublicClient): Promise<BlockInfo>;
        /** Fetches ENSRainbow version information */
        ensRainbowVersion?(): Promise<EnsRainbow.VersionInfo>;
    };
    /** Public clients for each blockchain network fetching data */
    publicClients: Record<number, PublicClient>;
}
interface PonderMetadataMiddlewareResponse<AppInfo, EnvVarsInfo extends PonderEnvVarsInfo, RuntimeInfo> {
    /** Application info */
    app: AppInfo;
    /** Dependencies info */
    deps: {
        /** Ponder application version */
        ponder: string;
        /** Node.js runtime version */
        nodejs: string;
    };
    /** Environment settings info */
    env: EnvVarsInfo;
    /** Runtime status info */
    runtime: RuntimeInfo;
}

/**
 * Ponder Metadata types definition.
 */
interface PonderMetadataModule {
    /** Application info */
    AppInfo: {
        /** Application name */
        name: string;
        /** Application version */
        version: string;
    };
    /** Environment Variables info */
    EnvVars: {
        /** Database schema */
        DATABASE_SCHEMA: string;
    } & PonderEnvVarsInfo;
    /** Runtime info */
    RuntimeInfo: {
        /**
         * Application build id
         * https://github.com/ponder-sh/ponder/blob/626e524/packages/core/src/build/index.ts#L425-L431
         **/
        codebaseBuildId: string;
        /** Network indexing status by chain ID */
        networkIndexingStatusByChainId: Record<number, NetworkIndexingStatus>;
        /** ENSRainbow version info */
        ensRainbow?: EnsRainbow.VersionInfo;
    };
}
type MetadataMiddlewareResponse = PonderMetadataMiddlewareResponse<PonderMetadataModule["AppInfo"], PonderMetadataModule["EnvVars"], PonderMetadataModule["RuntimeInfo"]>;
declare function ponderMetadata<AppInfo extends PonderMetadataModule["AppInfo"], EnvVars extends PonderMetadataModule["EnvVars"]>({ app, db, env, query, publicClients, }: PonderMetadataMiddlewareOptions<AppInfo, EnvVars>): MiddlewareHandler;

/**
 * Internal ponder metadata type.
 * Copied from https://github.com/ponder-sh/ponder/blob/32634897bf65e92a85dc4cccdaba70c9425d90f3/packages/core/src/database/index.ts#L94-L102
 */
type PonderAppMeta = {
    is_locked: 0 | 1;
    is_dev: 0 | 1;
    heartbeat_at: number;
    build_id: string;
    checkpoint: string;
    table_names: Array<string>;
    version: string;
};
/**
 * Get DB schema for _ponder_meta table.
 * Akin to https://github.com/ponder-sh/ponder/blob/32634897bf65e92a85dc4cccdaba70c9425d90f3/packages/core/src/database/index.ts#L129-L141
 *
 * @param databaseNamespace A namespace for the database.
 * @returns A table schema for _ponder_meta table.
 * */
declare const getPonderMetaTableSchema: (databaseNamespace: string) => drizzle_orm_pg_core.PgTableWithColumns<{
    name: "_ponder_meta";
    schema: undefined;
    columns: {
        key: drizzle_orm_pg_core.PgColumn<{
            name: "key";
            tableName: "_ponder_meta";
            dataType: "string";
            columnType: "PgText";
            data: "app";
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: true;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {
            $type: "app";
        }>;
        value: drizzle_orm_pg_core.PgColumn<{
            name: "value";
            tableName: "_ponder_meta";
            dataType: "json";
            columnType: "PgJsonb";
            data: PonderAppMeta;
            driverParam: unknown;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {
            $type: PonderAppMeta;
        }>;
    };
    dialect: "pg";
}> | drizzle_orm_pg_core.PgTableWithColumns<{
    name: "_ponder_meta";
    schema: string;
    columns: {
        key: drizzle_orm_pg_core.PgColumn<{
            name: "key";
            tableName: "_ponder_meta";
            dataType: "string";
            columnType: "PgText";
            data: "app";
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: true;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {
            $type: "app";
        }>;
        value: drizzle_orm_pg_core.PgColumn<{
            name: "value";
            tableName: "_ponder_meta";
            dataType: "json";
            columnType: "PgJsonb";
            data: PonderAppMeta;
            driverParam: unknown;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {
            $type: PonderAppMeta;
        }>;
    };
    dialect: "pg";
}>;
/**
 * Get DB schema for _ponder_status table.
 * Akin to https://github.com/ponder-sh/ponder/blob/32634897bf65e92a85dc4cccdaba70c9425d90f3/packages/core/src/database/index.ts#L143-L159
 *
 * @param databaseNamespace A namespace for the database.
 * @returns A table schema for _ponder_status table.
 */
declare const getPonderStatusTableSchema: (databaseNamespace: string) => drizzle_orm_pg_core.PgTableWithColumns<{
    name: "_ponder_status";
    schema: undefined;
    columns: {
        network_name: drizzle_orm_pg_core.PgColumn<{
            name: "network_name";
            tableName: "_ponder_status";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: true;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        block_number: drizzle_orm_pg_core.PgColumn<{
            name: "block_number";
            tableName: "_ponder_status";
            dataType: "number";
            columnType: "PgBigInt53";
            data: number;
            driverParam: string | number;
            notNull: false;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        block_timestamp: drizzle_orm_pg_core.PgColumn<{
            name: "block_timestamp";
            tableName: "_ponder_status";
            dataType: "number";
            columnType: "PgBigInt53";
            data: number;
            driverParam: string | number;
            notNull: false;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        ready: drizzle_orm_pg_core.PgColumn<{
            name: "ready";
            tableName: "_ponder_status";
            dataType: "boolean";
            columnType: "PgBoolean";
            data: boolean;
            driverParam: boolean;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
    };
    dialect: "pg";
}> | drizzle_orm_pg_core.PgTableWithColumns<{
    name: "_ponder_status";
    schema: string;
    columns: {
        network_name: drizzle_orm_pg_core.PgColumn<{
            name: "network_name";
            tableName: "_ponder_status";
            dataType: "string";
            columnType: "PgText";
            data: string;
            driverParam: string;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: true;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: [string, ...string[]];
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        block_number: drizzle_orm_pg_core.PgColumn<{
            name: "block_number";
            tableName: "_ponder_status";
            dataType: "number";
            columnType: "PgBigInt53";
            data: number;
            driverParam: string | number;
            notNull: false;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        block_timestamp: drizzle_orm_pg_core.PgColumn<{
            name: "block_timestamp";
            tableName: "_ponder_status";
            dataType: "number";
            columnType: "PgBigInt53";
            data: number;
            driverParam: string | number;
            notNull: false;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
        ready: drizzle_orm_pg_core.PgColumn<{
            name: "ready";
            tableName: "_ponder_status";
            dataType: "boolean";
            columnType: "PgBoolean";
            data: boolean;
            driverParam: boolean;
            notNull: true;
            hasDefault: false;
            isPrimaryKey: false;
            isAutoincrement: false;
            hasRuntimeDefault: false;
            enumValues: undefined;
            baseColumn: never;
            identity: undefined;
            generated: undefined;
        }, {}, {}>;
    };
    dialect: "pg";
}>;
type PonderStatusTableSchema = ReturnType<typeof getPonderStatusTableSchema>;
/**
 * Get a list of ponder status entries for each network.
 *
 * @param namespace A namespace for the database (e.g. "public").
 * @param db Drizzle DB Client instance.
 * @returns a list of ponder status entries for each network.
 */
declare function queryPonderStatus(namespace: string, db: ReadonlyDrizzle<Record<string, unknown>>): Promise<Array<PonderStatusTableSchema["$inferSelect"]>>;
type PonderMetaTableSchema = ReturnType<typeof getPonderMetaTableSchema>;
/**
 * Get ponder metadata for the app.
 *
 * @param namespace A namespace for the database (e.g. "public").
 * @param db Drizzle DB Client instance.
 * @returns ponder metadata for the app.
 * @throws Error if ponder metadata not found.
 */
declare function queryPonderMeta(namespace: string, db: ReadonlyDrizzle<Record<string, unknown>>): Promise<PonderMetaTableSchema["$inferSelect"]["value"]>;

declare module "parse-prometheus-text-format" {
    interface PrometheusMetric {
        name: string;
        help: string;
        type: string;
        metrics: Array<{
            value: string;
            labels?: Record<string, string>;
        }>;
    }
    export default function parsePrometheusTextFormat(text: string): Array<PrometheusMetric>;
}

declare class PrometheusMetrics {
    private readonly metrics;
    private constructor();
    static parse(maybePrometheusMetricsText: string): PrometheusMetrics;
    /**
     * Gets all metrics of a specific name
     * @param name Metric name
     * @returns Array of metrics or undefined if not found
     * @example
     * ```ts
     * const metrics = parser.get('ponder_historical_total_indexing_seconds');
     * // Returns: [
     * //   { value: 251224935, labels: { network: "1" } },
     * //   { value: 251224935, labels: { network: "8453" } }
     * // ]
     * ```
     */
    get(name: string): Array<{
        value: number;
        labels?: Record<string, string>;
    }> | undefined;
    /**
     * Gets a single metric value, optionally filtered by labels
     * @param name Metric name
     * @param labelFilter Optional label key-value pairs to match
     * @returns Metric value or undefined if not found
     * @example
     * ```ts
     * // Get simple value
     * parser.getValue('ponder_historical_start_timestamp_seconds') // Returns: 1740391265
     *
     * // Get value with label filter
     * parser.getValue('ponder_historical_total_indexing_seconds', { network: '1' }) // Returns: 251224935
     * ```
     */
    getValue(name: string, labelFilter?: Record<string, string>): number | undefined;
    /**
     * Gets a label value from a metric
     * @param name Metric name
     * @param label Label name to retrieve
     * @returns Label value or undefined if not found
     * @example
     * ```ts
     * parser.getLabel('ponder_version_info', 'version') // Returns: "0.9.18"
     * parser.getLabel('ponder_settings_info', 'ordering') // Returns: "omnichain"
     * ```
     */
    getLabel(name: string, label: string): string | undefined;
    /**
     * Gets all unique label values for a metric
     * @param name Metric name
     * @param label Label name to retrieve
     * @returns Array of unique label values
     * @example
     * ```ts
     * // Get all network IDs
     * parser.getLabels('ponder_historical_total_indexing_seconds', 'network')
     * // Returns: ['1', '8453']
     * ```
     */
    getLabels(name: string, label: string): string[];
    /**
     * Gets help text for a metric
     * @param name Metric name
     * @returns Help text or undefined if not found
     * @example
     * ```ts
     * parser.getHelp('ponder_historical_start_timestamp_seconds')
     * // Returns: "Timestamp at which historical indexing started"
     * ```
     */
    getHelp(name: string): string | undefined;
    /**
     * Gets metric type
     * @param name Metric name
     * @returns Metric type or undefined if not found
     * @example
     * ```ts
     * parser.getType('ponder_version_info') // Returns: "gauge"
     * parser.getType('ponder_postgres_query_total') // Returns: "counter"
     * ```
     */
    getType(name: string): string | undefined;
    /**
     * Gets all metric names
     * @returns Array of metric names
     * @example
     * ```ts
     * parser.getMetricNames()
     * // Returns: [
     * //   'ponder_version_info',
     * //   'ponder_settings_info',
     * //   'ponder_historical_start_timestamp_seconds',
     * //   'ponder_historical_total_indexing_seconds'
     * // ]
     * ```
     */
    getMetricNames(): string[];
}

export { type BlockInfo, type MetadataMiddlewareResponse, type NetworkIndexingStatus, type PonderMetadataMiddlewareResponse, PrometheusMetrics, ponderMetadata, queryPonderMeta, queryPonderStatus };
