/**
 * Structured Logging Service
 *
 * Provides structured logging with automatic trace context injection,
 * log levels, and consistent formatting for observability.
 *
 * @packageDocumentation
 */
import { pino } from 'pino';
import { trace } from '@opentelemetry/api';
// ============================================================================
// Default Configuration
// ============================================================================
const DEFAULT_CONFIG = {
    level: 'info',
    pretty: process.env.NODE_ENV !== 'production',
    includeTraceContext: true,
    redact: ['password', 'apiKey', 'secret', 'token', 'authorization'],
    serviceName: 'vorion',
};
// ============================================================================
// Trace Context Extraction
// ============================================================================
/**
 * Extract trace context from current OpenTelemetry context
 */
function extractTraceContext() {
    const activeSpan = trace.getActiveSpan();
    if (!activeSpan) {
        return {};
    }
    const spanContext = activeSpan.spanContext();
    if (!spanContext || !trace.isSpanContextValid(spanContext)) {
        return {};
    }
    return {
        traceId: spanContext.traceId,
        spanId: spanContext.spanId,
    };
}
// ============================================================================
// Structured Logger Implementation
// ============================================================================
class StructuredLoggerImpl {
    logger;
    config;
    bindings;
    constructor(config, bindings = {}) {
        this.config = config;
        this.bindings = bindings;
        const pinoConfig = {
            level: config.level,
            redact: config.redact,
            base: {
                service: config.serviceName,
                ...bindings,
            },
            formatters: {
                level: (label) => ({ level: label }),
                bindings: (bindings) => bindings,
            },
            timestamp: pino.stdTimeFunctions.isoTime,
        };
        if (config.pretty) {
            this.logger = pino({
                ...pinoConfig,
                transport: {
                    target: 'pino-pretty',
                    options: {
                        colorize: true,
                        translateTime: 'SYS:standard',
                        ignore: 'pid,hostname',
                    },
                },
            });
        }
        else {
            this.logger = pino(pinoConfig);
        }
    }
    enrichContext(ctx) {
        const enriched = { ...ctx };
        // Add trace context if enabled and not already present
        if (this.config.includeTraceContext && !ctx.traceId) {
            const traceCtx = extractTraceContext();
            if (traceCtx.traceId) {
                enriched.traceId = traceCtx.traceId;
                enriched.spanId = traceCtx.spanId;
            }
        }
        return enriched;
    }
    trace(ctx, msg) {
        this.logger.trace(this.enrichContext(ctx), msg);
    }
    debug(ctx, msg) {
        this.logger.debug(this.enrichContext(ctx), msg);
    }
    info(ctx, msg) {
        this.logger.info(this.enrichContext(ctx), msg);
    }
    warn(ctx, msg) {
        this.logger.warn(this.enrichContext(ctx), msg);
    }
    error(ctx, msg) {
        this.logger.error(this.enrichContext(ctx), msg);
    }
    fatal(ctx, msg) {
        this.logger.fatal(this.enrichContext(ctx), msg);
    }
    child(bindings) {
        return new StructuredLoggerImpl(this.config, { ...this.bindings, ...bindings });
    }
}
// ============================================================================
// Factory Functions
// ============================================================================
let globalLogger = null;
let globalConfig = DEFAULT_CONFIG;
/**
 * Initialize logging with configuration
 */
export function initLogging(config = {}) {
    globalConfig = { ...DEFAULT_CONFIG, ...config };
    globalLogger = new StructuredLoggerImpl(globalConfig);
    return globalLogger;
}
/**
 * Get the global logger instance
 */
export function getLogger() {
    if (!globalLogger) {
        globalLogger = new StructuredLoggerImpl(globalConfig);
    }
    return globalLogger;
}
/**
 * Create a component-scoped logger
 */
export function createComponentLogger(component) {
    const base = getLogger();
    return base.child({ component });
}
// ============================================================================
// Specialized Loggers
// ============================================================================
/**
 * Create an Agent Anchor logger with CAR context
 */
export function createAgentLogger(carId, tenantId) {
    return getLogger().child({ carId, tenantId, component: 'agent-anchor' });
}
/**
 * Create an A2A logger with call chain context
 */
export function createA2ALogger(requestId, callerCarId, calleeCarId) {
    return getLogger().child({
        requestId,
        callerCarId,
        calleeCarId,
        component: 'a2a',
    });
}
/**
 * Create a sandbox logger with container context
 */
export function createSandboxLogger(containerId, carId, tier) {
    return getLogger().child({
        containerId,
        carId,
        tier,
        component: 'sandbox',
    });
}
// ============================================================================
// Log Helpers
// ============================================================================
/**
 * Log an agent lifecycle event
 */
export function logAgentEvent(logger, event, carId, details) {
    logger.info({ event: `agent.${event}`, carId, ...details }, `Agent ${event}: ${carId}`);
}
/**
 * Log a trust score change
 */
export function logTrustChange(logger, carId, oldScore, newScore, oldTier, newTier, reason) {
    const tierChanged = oldTier !== newTier;
    const ctx = {
        event: tierChanged ? 'trust.tier_change' : 'trust.score_change',
        carId,
        oldScore,
        newScore,
        oldTier,
        newTier,
        reason,
    };
    if (tierChanged) {
        logger.info(ctx, `Trust tier changed: ${carId} T${oldTier} -> T${newTier}`);
    }
    else {
        logger.debug(ctx, `Trust score updated: ${carId} ${oldScore} -> ${newScore}`);
    }
}
/**
 * Log an A2A invocation
 */
export function logA2AInvocation(logger, phase, callerCarId, calleeCarId, action, details) {
    const ctx = {
        event: `a2a.invoke.${phase}`,
        callerCarId,
        calleeCarId,
        action,
        ...details,
    };
    switch (phase) {
        case 'start':
            logger.info(ctx, `A2A invoke: ${callerCarId} -> ${calleeCarId}:${action}`);
            break;
        case 'success':
            logger.info(ctx, `A2A success: ${callerCarId} -> ${calleeCarId}:${action}`);
            break;
        case 'failure':
            logger.warn(ctx, `A2A failed: ${callerCarId} -> ${calleeCarId}:${action}`);
            break;
        case 'timeout':
            logger.warn(ctx, `A2A timeout: ${callerCarId} -> ${calleeCarId}:${action}`);
            break;
    }
}
/**
 * Log a sandbox event
 */
export function logSandboxEvent(logger, event, containerId, details) {
    const ctx = {
        event: `sandbox.${event}`,
        containerId,
        ...details,
    };
    if (event === 'violation') {
        logger.warn(ctx, `Sandbox violation: ${containerId}`);
    }
    else {
        logger.info(ctx, `Sandbox ${event}: ${containerId}`);
    }
}
/**
 * Log an attestation
 */
export function logAttestation(logger, type, carId, outcome, details) {
    const ctx = {
        event: 'attestation.recorded',
        type,
        carId,
        outcome,
        ...details,
    };
    logger.info(ctx, `Attestation recorded: ${type} for ${carId}`);
}
//# sourceMappingURL=logging.js.map