/**
 * Prometheus Metrics (prom-client)
 *
 * Lazy-initialized so importing this module is safe in non-Node runtimes.
 */
import { Env } from '../config/env.js';
let statePromise = null;
const DEFAULT_CONTENT_TYPE = 'text/plain; version=0.0.4; charset=utf-8';
const createNoopState = () => {
    const noopCounter = { inc: () => undefined };
    const noopHistogram = { observe: () => undefined };
    const noopRegistry = {
        contentType: DEFAULT_CONTENT_TYPE,
        metrics: () => '',
    };
    return {
        client: {},
        registry: noopRegistry,
        httpRequestsTotal: noopCounter,
        httpRequestDurationSeconds: noopHistogram,
        dbQueriesTotal: noopCounter,
        dbQueryDurationSeconds: noopHistogram,
    };
};
async function ensureState() {
    if (statePromise !== null)
        return statePromise;
    statePromise = (async () => {
        let client;
        try {
            client = await import('prom-client');
        }
        catch {
            // prom-client is intentionally optional at runtime.
            return createNoopState();
        }
        const registry = new client.Registry();
        const appName = Env.get('APP_NAME', 'ZinTrust');
        if (appName.trim() !== '') {
            registry.setDefaultLabels({ app: appName });
        }
        // Default metrics (process/memory/event loop) for Node runtimes.
        // `collectDefaultMetrics` exists in prom-client; keep this lazy and best-effort.
        try {
            client.collectDefaultMetrics({ register: registry });
        }
        catch {
            // ignore
        }
        const httpRequestsTotal = new client.Counter({
            name: 'http_requests_total',
            help: 'Total number of HTTP requests',
            labelNames: ['method', 'route', 'status'],
            registers: [registry],
        });
        const httpRequestDurationSeconds = new client.Histogram({
            name: 'http_request_duration_seconds',
            help: 'HTTP request duration in seconds',
            labelNames: ['method', 'route', 'status'],
            // Sensible default buckets for web apps (in seconds)
            buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
            registers: [registry],
        });
        const dbQueriesTotal = new client.Counter({
            name: 'db_queries_total',
            help: 'Total number of database queries',
            labelNames: ['driver'],
            registers: [registry],
        });
        const dbQueryDurationSeconds = new client.Histogram({
            name: 'db_query_duration_seconds',
            help: 'Database query duration in seconds',
            labelNames: ['driver'],
            buckets: [0.001, 0.0025, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5],
            registers: [registry],
        });
        return {
            client,
            registry,
            httpRequestsTotal,
            httpRequestDurationSeconds,
            dbQueriesTotal,
            dbQueryDurationSeconds,
        };
    })();
    return statePromise;
}
export const PrometheusMetrics = Object.freeze({
    async getMetricsText() {
        const state = await ensureState();
        const body = await state.registry.metrics();
        const contentType = typeof state.registry.contentType === 'string'
            ? state.registry.contentType
            : DEFAULT_CONTENT_TYPE;
        return { contentType, body };
    },
    async observeHttpRequest(input) {
        const state = await ensureState();
        const method = input.method || 'UNKNOWN';
        const route = input.route || 'unknown';
        const status = Number.isFinite(input.status) ? String(input.status) : '0';
        const durationSeconds = Math.max(0, input.durationMs / 1000);
        state.httpRequestsTotal.inc({ method, route, status }, 1);
        state.httpRequestDurationSeconds.observe({ method, route, status }, durationSeconds);
    },
    async observeDbQuery(input) {
        const state = await ensureState();
        const driver = input.driver || 'unknown';
        const durationSeconds = Math.max(0, input.durationMs / 1000);
        state.dbQueriesTotal.inc({ driver }, 1);
        state.dbQueryDurationSeconds.observe({ driver }, durationSeconds);
    },
});
export default PrometheusMetrics;
