/**
* Copyright Super iPaaS Integration LLC, an IBM Company 2024
*/
import AdmZip from 'adm-zip';
import { showError } from '../../helpers/common/message-helper.js';
import {
	checkForRootDirPermission,
	checkIfAllProjectExists,
	checkIfRootDirExists
} from '../../helpers/apim/root-dir-helper.js';
import { checkAndLoadDependencies } from '../../helpers/apim/build-helper.js';
import { executeBuildProject } from './projects-builder.js';
import { processProjectBuild } from '@apic/studio-build';
import { addValidAssetsToZip } from '../../helpers/common/zip-helper.js';
import path from 'path';

jest.mock('adm-zip');
jest.mock('../../helpers/common/message-helper.js', () => ({
	showError: jest.fn(),
	showInfo: jest.fn()
}));
jest.mock('../../helpers/apim/root-dir-helper.js', () => ({
	checkForRootDirPermission: jest.fn(),
	checkIfAllProjectExists: jest.fn(),
	checkIfRootDirExists: jest.fn()
}));
jest.mock('../../helpers/apim/build-helper.js', () => ({
	checkAndLoadDependencies: jest.fn()
}));
jest.mock('@apic/studio-build', () => ({
	processProjectBuild: jest.fn()
}));
jest.mock('../../helpers/common/zip-helper.js', () => ({
	addValidAssetsToZip: jest.fn()
}));
const excludedKinds = ['test', 'environment', 'assertion'];

describe('Projects builder test suite', () => {
	const rootDirPath = 'mock/root/dir';
	const projectNames = 'projA,projB';

	beforeEach(() => {
		jest.clearAllMocks();
	});

	it('should validate rootDirPath and projectNames, build projects, load dependencies, and return zip buffer', async () => {
		const mockZip = {
			toBuffer: jest.fn().mockReturnValue(Buffer.from('mockZipBuffer'))
		};
		(AdmZip as jest.Mock).mockImplementation(() => mockZip);
    
		const mockProcessProjectBuild = jest.fn().mockResolvedValue(Buffer.from('mockProcessedZipBuffer'));
		(processProjectBuild as jest.Mock).mockImplementation(mockProcessProjectBuild);
    
		const result = await executeBuildProject(rootDirPath, projectNames);
    

		expect(checkIfRootDirExists).toHaveBeenCalledWith(rootDirPath);
		expect(checkForRootDirPermission).toHaveBeenCalledWith(rootDirPath);
		expect(checkIfAllProjectExists).toHaveBeenCalledWith(rootDirPath, projectNames);
    
		expect(addValidAssetsToZip).toHaveBeenCalledWith(
			path.join(rootDirPath, 'projA'),
			'projA',
			mockZip,
			excludedKinds,
		);
		expect(addValidAssetsToZip).toHaveBeenCalledWith(
			path.join(rootDirPath, 'projB'),
			'projB',
			mockZip,
			excludedKinds,
		);
    
		expect(checkAndLoadDependencies).toHaveBeenCalledWith(rootDirPath, projectNames, mockZip);
		expect(mockProcessProjectBuild).toHaveBeenCalledWith(Buffer.from('mockZipBuffer'));
		expect(result).toEqual(Buffer.from('mockProcessedZipBuffer'));
	});
    

	it('should catch errors, display an error message, and exit the process', async () => {
		const errorMessage = 'mock error message';
		(checkIfRootDirExists as jest.Mock).mockImplementation(() => { throw new Error(errorMessage); });

		const processExitSpy = jest.spyOn(process, 'exit').mockImplementation(() => { throw new Error('process.exit'); });

		await expect(executeBuildProject(rootDirPath, projectNames)).rejects.toThrow('process.exit');

		expect(showError).toHaveBeenCalledWith(errorMessage);
		expect(processExitSpy).toHaveBeenCalledWith(1);
	});
});
