import { Readable } from 'node:stream';
import { encode as encodeStream, decode as decodeStream } from '../../dist/stream/index.js';
import { EXPECTED, INPUTS } from './.data.ts';

describe('stream', () => {
    it.each(Object.keys(INPUTS))('%s', async (name) => {
        const input = INPUTS[name];
        const expected = EXPECTED[name] ?? input;
        if (expected instanceof Error) {
            await expect(async () => {
                const encoded = await Readable.fromWeb(encodeStream(input) as never).toArray();
                const decoded = await decodeStream(
                    Readable.toWeb(Readable.from(encoded)) as ReadableStream<Uint8Array<ArrayBuffer>>,
                );
                expect(decoded).toEqual(expected);
            }).rejects.toThrow(expected);
        } else {
            const encoded = await Readable.fromWeb(encodeStream(input) as never).toArray();
            const data = encoded.flatMap((chunk: Buffer<ArrayBuffer>) => {
                if (chunk.length < 2) return [chunk];
                // split to random chunks
                const chunks = [];
                let offset = 0;
                while (offset < chunk.length) {
                    const size = Math.floor(Math.random() * chunk.length);
                    chunks.push(chunk.subarray(offset, offset + size));
                    offset += size;
                }
                return chunks;
            });
            const decoded = await decodeStream(
                Readable.toWeb(Readable.from(data)) as ReadableStream<Uint8Array<ArrayBuffer>>,
            );
            expect(decoded).toEqual(expected);
        }
    });
});
