import { SpanStatusCode } from '../types.js';
import { summarizeError } from '../../../utils/error-display.js';
import { logger } from '../../../utils/logger.js';
/**
 * ConsoleExporter — prints span data to stderr for development.
 *
 * Usage:
 * ```ts
 * const exporter = new ConsoleExporter({ verbosity: 'standard' });
 * ```
 */
export class ConsoleExporter {
    name = 'console';
    verbosity;
    constructor(config = {}) {
        this.verbosity = config.verbosity ?? 'standard';
    }
    /** Export spans by printing formatted summaries to stderr. */
    async export(spans) {
        for (const span of spans) {
            let line;
            try {
                line = this._format(span);
            }
            catch (err) {
                this._logSpanFailure('[ConsoleExporter] span formatting failed', span, err);
                continue;
            }
            try {
                process.stderr.write(line + '\n', (err) => {
                    if (err) {
                        this._logSpanFailure('[ConsoleExporter] stderr write failed', span, err);
                    }
                });
            }
            catch (err) {
                this._logSpanFailure('[ConsoleExporter] stderr write failed', span, err);
            }
        }
    }
    /** Flush is a no-op because this exporter does not own buffering. */
    async flush() {
        // Nothing buffered.
    }
    /** Shutdown is a no-op. */
    async shutdown() {
        // Nothing to tear down.
    }
    /** Format a single span for console output. */
    _format(span) {
        const status = span.status.code === SpanStatusCode.ERROR
            ? 'ERROR'
            : span.status.code === SpanStatusCode.OK
                ? 'OK'
                : 'UNSET';
        const base = `[otel] ${span.name} | ${status} | ${span.durationMs}ms` +
            ` | trace=${span.spanContext.traceId.slice(0, 8)} span=${span.spanContext.spanId.slice(0, 8)}`;
        if (this.verbosity === 'minimal') {
            return base;
        }
        const attrEntries = Object.entries(span.attributes);
        const attrStr = attrEntries.length === 0
            ? ''
            : '\n  attrs: ' +
                attrEntries
                    .map(([k, v]) => {
                    const val = this.verbosity === 'verbose'
                        ? JSON.stringify(v)
                        : typeof v === 'string' && v.length > 64
                            ? JSON.stringify(v.slice(0, 64) + '...')
                            : JSON.stringify(v);
                    return `${k}=${val}`;
                })
                    .join(' ');
        if (this.verbosity === 'standard') {
            return base + attrStr;
        }
        // verbose — include events
        const eventsStr = span.events.length === 0
            ? ''
            : '\n  events: ' +
                span.events
                    .map((e) => `${e.name}@${e.timestamp}`)
                    .join(', ');
        if (span.status.message) {
            return base + attrStr + eventsStr + `\n  message: ${span.status.message}`;
        }
        return base + attrStr + eventsStr;
    }
    _logSpanFailure(message, span, error) {
        logger.warn(message, {
            error: summarizeError(error),
            spanName: span.name,
            traceId: span.spanContext.traceId,
            spanId: span.spanContext.spanId,
        });
    }
}
