import { describe, it, expect, vi, afterEach } from 'vitest';
import { PassThrough } from 'stream';
import { EventEmitter } from 'events';

vi.mock('child_process', () => ({ spawn: vi.fn() }));
import * as child_process from 'child_process';
import { streamArchiveEntry } from '../../src/services/archiveReader';

afterEach(() => {
  vi.restoreAllMocks();
});

describe('services/archiveReader streamArchiveEntry', () => {
  it('streams entry using 7z stdout', async () => {
    const pass = new PassThrough();
    const proc = new EventEmitter() as any;
    proc.stdout = pass;

    (child_process.spawn as any).mockImplementation(() => proc as any);

    // Emular producción de datos de forma asíncrona
    setImmediate(() => {
      pass.write(Buffer.from('content-from-7z'));
      pass.end();
    });

    const stream = await streamArchiveEntry('/roms/archive.7z', 'path/file.txt');
    expect(stream).not.toBeNull();

    const chunks: Buffer[] = [];
    for await (const chunk of stream as any) {
      chunks.push(Buffer.from(chunk));
    }

    expect(Buffer.concat(chunks).toString()).toBe('content-from-7z');
  });

  it('falls back to unzip -p when 7z throws', async () => {
    const pass = new PassThrough();
    const proc2 = new EventEmitter() as any;
    proc2.stdout = pass;

    (child_process.spawn as any)
      .mockImplementationOnce(() => {
        throw new Error('spawn ENOENT');
      })
      .mockImplementationOnce(() => proc2 as any);

    setImmediate(() => {
      pass.write(Buffer.from('fallback-content'));
      pass.end();
    });

    const stream = await streamArchiveEntry('/roms/archive.zip', 'file.dat');
    expect(stream).not.toBeNull();

    const chunks: Buffer[] = [];
    for await (const chunk of stream as any) {
      chunks.push(Buffer.from(chunk));
    }

    expect(Buffer.concat(chunks).toString()).toBe('fallback-content');
  });

  it('returns null for unsupported formats', async () => {
    const res = await streamArchiveEntry('/roms/archive.bin', 'entry');
    expect(res).toBeNull();
  });
});
