/**
 * Bounded response-body accumulator.
 *
 * Used by HTTP monitor checks that need to scan response bodies for keyword
 * assertions. Caps total bytes ingested so a hostile (or honest-but-huge)
 * target can't OOM the worker. Stringifies once in `.value()` to avoid
 * redundant UTF-8 decoding on every chunk and to keep multi-byte sequences
 * intact across chunk boundaries.
 */
export interface BoundedBuffer {
    /** Append a chunk. Returns false once the cap is reached — caller should destroy the stream. */
    append(chunk: Buffer | string): boolean;
    /** Concatenate every retained chunk and decode as UTF-8. */
    value(): string;
    readonly exceeded: boolean;
    readonly bytes: number;
}

export function createBoundedBuffer(maxBytes: number): BoundedBuffer {
    if (!Number.isFinite(maxBytes) || maxBytes <= 0) {
        throw new Error(`createBoundedBuffer: maxBytes must be a positive number, got ${maxBytes}`);
    }

    const chunks: Buffer[] = [];
    let bytes = 0;
    let exceeded = false;

    return {
        append(chunk: Buffer | string): boolean {
            if (exceeded) return false;
            const buf = typeof chunk === 'string' ? Buffer.from(chunk, 'utf8') : chunk;
            if (bytes + buf.length > maxBytes) {
                exceeded = true;
                return false;
            }
            chunks.push(buf);
            bytes += buf.length;
            return true;
        },
        value(): string {
            return Buffer.concat(chunks, bytes).toString('utf8');
        },
        get exceeded(): boolean { return exceeded; },
        get bytes(): number { return bytes; },
    };
}
