/**
 * Error-path tests for ScaffoldService — tests the archiver finalize error handler.
 * These tests use jest.mock('archiver') to simulate archiver failures.
 */

import { PassThrough } from 'stream';

// Mock archiver before importing ScaffoldService
const mockFinalize = jest.fn();
const mockArchive = {
  pipe: jest.fn(),
  append: jest.fn(),
  finalize: mockFinalize,
};
jest.mock('archiver', () => jest.fn(() => mockArchive));

// Mock metrics to avoid registry conflicts
jest.mock('../../../src/metrics/registry', () => ({
  scaffoldGeneratedTotal: { labels: jest.fn().mockReturnValue({ inc: jest.fn() }) },
  scaffoldGenerationDurationMs: { labels: jest.fn().mockReturnValue({ observe: jest.fn() }) },
}));

import { ScaffoldService } from '../../../src/services/ScaffoldService';

const BASE_OPTIONS = {
  agentId: 'agent-uuid-1234',
  agentName: 'my-test-agent',
  clientId: 'client-id-5678',
  apiUrl: 'https://api.sentryagent.ai',
};

describe('ScaffoldService — archiver error path', () => {
  let service: ScaffoldService;

  beforeEach(() => {
    jest.clearAllMocks();
    // Reset pipe to actually pipe to the PassThrough so the stream reference is correct
    mockArchive.pipe.mockImplementation(() => {});
    service = new ScaffoldService();
  });

  it('destroys the PassThrough stream when archiver finalize rejects with an Error', async () => {
    const archiverError = new Error('archiver finalize failure');
    mockFinalize.mockReturnValue(Promise.reject(archiverError));

    const { stream } = await service.generateScaffold({
      ...BASE_OPTIONS,
      language: 'typescript',
    });

    // Attach error listener to suppress unhandled error event from stream.destroy(err)
    await new Promise<void>((resolve) => {
      stream.on('error', () => resolve());
    });

    expect((stream as PassThrough).destroyed).toBe(true);
  });

  it('destroys the PassThrough stream when archiver finalize rejects with a non-Error value', async () => {
    // Covers the `err instanceof Error ? err : new Error(String(err))` false branch
    mockFinalize.mockReturnValue(Promise.reject('string-error'));

    const { stream } = await service.generateScaffold({
      ...BASE_OPTIONS,
      language: 'typescript',
    });

    // Attach error listener to suppress unhandled error event from stream.destroy(err)
    await new Promise<void>((resolve) => {
      stream.on('error', () => resolve());
    });

    expect((stream as PassThrough).destroyed).toBe(true);
  });
});
