/**
* Copyright Super iPaaS Integration LLC, an IBM Company 2024
*/
import { executeBuildProjectAssets } from './project-assets-builder.js';
import { showError} from '../../helpers/common/message-helper.js';
import {
	checkForRootDirPermission,
	checkIfProjectExists,
	checkIfRootDirExists
} from '../../helpers/apim/root-dir-helper.js';
import { searchAsset } from '../../helpers/apim/build-helper.js';
import { getSubDirectory, normalizePath, readFile } from '../../helpers/common/fs-helper.js';
import { readYaml } from '../../helpers/common/yaml-helper.js';
import { getAPIDefPath } from '../../handlers/api-asset-handler.js';
import { processProjectBuild } from '@apic/studio-build';

jest.mock('../../helpers/common/message-helper.js', () => ({
	showError: jest.fn(),
	showInfo: jest.fn(),
}));

jest.mock('../../helpers/apim/root-dir-helper.js', () => ({
	checkForRootDirPermission: jest.fn(),
	checkIfProjectExists: jest.fn(),
	checkIfRootDirExists: jest.fn(),
}));

jest.mock('../../helpers/apim/build-helper.js', () => ({
	checkAndLoadDependencies: jest.fn(),
	searchAsset: jest.fn(),
}));

jest.mock('../../helpers/common/fs-helper.js', () => ({
	getParentDir: jest.fn(),
	getSubDirectory: jest.fn(),
	normalizePath: jest.fn(),
	readFile: jest.fn(),
}));

jest.mock('../../helpers/common/yaml-helper.js', () => ({
	readYaml: jest.fn(),
}));

jest.mock('../../handlers/api-asset-handler.js', () => ({
	getAPIDefPath: jest.fn(),
}));

jest.mock('@apic/studio-build', () => ({
	processProjectBuild: jest.fn(),
}));

jest.mock('adm-zip', () => {
	return jest.fn().mockImplementation(() => ({
		addLocalFile: jest.fn(),
		toBuffer: jest.fn().mockReturnValue(Buffer.from('mocked-buffer')),
	}));
});

describe('Project assets builder test suite', () => {
	const project = 'test-project';
	const rootDirPath = 'test/root/dir';
	const assets = 'asset1,asset2';

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

	it('should build project assets successfully', async () => {
		(checkIfRootDirExists as jest.Mock).mockImplementation(() => {});
		(checkForRootDirPermission as jest.Mock).mockImplementation(() => {});
		(checkIfProjectExists as jest.Mock).mockImplementation(() => {});
		(searchAsset as jest.Mock).mockReturnValue({ parentPath: 'test/path', name: 'asset1' });
		(getAPIDefPath as jest.Mock).mockReturnValue('api-definition-path');
		(getSubDirectory as jest.Mock).mockReturnValue('test/project/dir');
		(normalizePath as jest.Mock).mockImplementation(path => path);
		(readFile as jest.Mock).mockReturnValue('{}');
		(readYaml as jest.Mock).mockReturnValue({});
		(processProjectBuild as jest.Mock).mockResolvedValue(Buffer.from('mocked-buffer'));

		const buffer = await executeBuildProjectAssets(project, rootDirPath, assets);

		expect(buffer).toEqual(Buffer.from('mocked-buffer'));
		expect(checkIfRootDirExists).toHaveBeenCalledWith(rootDirPath);
		expect(checkForRootDirPermission).toHaveBeenCalledWith(rootDirPath);
		expect(checkIfProjectExists).toHaveBeenCalledWith(rootDirPath, project);
	});

	it('should build project assets for relative path in $path successfully', async () => {
		(checkIfRootDirExists as jest.Mock).mockImplementation(() => {});
		(checkForRootDirPermission as jest.Mock).mockImplementation(() => {});
		(checkIfProjectExists as jest.Mock).mockImplementation(() => {});
		(searchAsset as jest.Mock).mockReturnValue({ parentPath: 'test/path', name: 'asset1' });
		(getAPIDefPath as jest.Mock).mockReturnValue('../../api-definition-path');
		(getSubDirectory as jest.Mock).mockReturnValue('test/project/dir');
		(normalizePath as jest.Mock).mockImplementation(path => path);
		(readFile as jest.Mock).mockReturnValue('{}');
		(readYaml as jest.Mock).mockReturnValue({});
		(processProjectBuild as jest.Mock).mockResolvedValue(Buffer.from('mocked-buffer'));

		const buffer = await executeBuildProjectAssets(project, rootDirPath, assets);

		expect(buffer).toEqual(Buffer.from('mocked-buffer'));
		expect(checkIfRootDirExists).toHaveBeenCalledWith(rootDirPath);
		expect(checkForRootDirPermission).toHaveBeenCalledWith(rootDirPath);
		expect(checkIfProjectExists).toHaveBeenCalledWith(rootDirPath, project);
	});

	it('should handle errors and call process.exit to end process', async () => {
		const processExitSpy = jest.spyOn(process, 'exit').mockImplementation(() => { throw new Error('process.exit'); });
		(checkIfRootDirExists as jest.Mock).mockImplementation(() => { throw new Error('Root directory error'); });
		await expect(executeBuildProjectAssets(project, rootDirPath, assets)).rejects.toThrow('process.exit');
		expect(showError).toHaveBeenCalledWith('Root directory error');
		expect(processExitSpy).toHaveBeenCalledWith(1);
	});
});
