import { buildAction } from './build-action.js';
import { BuildOptionsModel } from '../model/studio/command-options/build-options-model.js';
import { buildAssets, buildProjects, getOutputPath } from './helpers/build-action-helper.js';
import { convertAdmToJsZip } from '../converters/adm-to-jszip-convertor.js';
import { showSuccess, showWarning } from '../helpers/common/message-helper.js';
import { IGNORE_PROJECT_ARG, BUILD_SUCCESSFUL, CREATED_BUILD_ZIP } from '../constants/message-constants.js';
import { DebugManager } from '../debug/debug-manager.js';
import { createBuildZip } from '../helpers/common/fs-helper.js';

jest.mock('./helpers/build-action-helper.js', () => ({
	buildAssets: jest.fn(),
	buildProjects: jest.fn(),
	getOutputPath:jest.fn()
}));
jest.mock('./test-action.js', () => ({
    setupDebugManager: jest.fn(),
}));


jest.mock('../converters/adm-to-jszip-convertor.js', () => ({
	convertAdmToJsZip: jest.fn(),
}));

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

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

jest.mock('../debug/debug-manager.js', () => ({
	DebugManager: {
		getInstance: jest.fn().mockReturnValue({
			setDebugEnabled: jest.fn(),
		}),
	},
}));


describe('buildAction test suite', () => {
	const localDir = 'mock/root/dir';
	const outputPath = 'mock/output/path';
	const projectName = 'myProject';

	const optionsWithNames: BuildOptionsModel = {
		all: false,
		localDir,
		output: outputPath,
		project: projectName,
		names: 'projA,projB',
		debug: true,
	};

	const optionsWithoutNames: BuildOptionsModel = {
		all: true,
		localDir,
		output: outputPath,
		project: projectName,
		names: '',
		debug: true,
	};

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

	it('should build assets with names and write to output path', async () => {
		const mockZipBuffer = Buffer.from('mockZipBuffer');
		const mockConvertedBuffer = Buffer.from('mockConvertedBuffer');

		(buildAssets as jest.Mock).mockResolvedValue(mockZipBuffer);
		(convertAdmToJsZip as jest.Mock).mockResolvedValue(mockConvertedBuffer);
		(createBuildZip as jest.Mock).mockResolvedValue(true);

		await buildAction(projectName, optionsWithNames);

		expect(buildAssets).toHaveBeenCalledWith('projA,projB', localDir, projectName);
		expect(convertAdmToJsZip).toHaveBeenCalledWith(mockZipBuffer);
		expect(createBuildZip).toHaveBeenCalledWith(mockConvertedBuffer, outputPath);
		expect(showSuccess).toHaveBeenCalledWith(BUILD_SUCCESSFUL);
		expect(showSuccess).toHaveBeenCalledWith(CREATED_BUILD_ZIP + outputPath);
	});

	it('should build projects without names and write to output path', async () => {
		const mockZipBuffer = Buffer.from('mockZipBuffer');
		const mockConvertedBuffer = Buffer.from('mockConvertedBuffer');

		(buildProjects as jest.Mock).mockResolvedValue(mockZipBuffer);
		(convertAdmToJsZip as jest.Mock).mockResolvedValue(mockConvertedBuffer);
		(createBuildZip as jest.Mock).mockResolvedValue(true);

		await buildAction(projectName, optionsWithoutNames);

		expect(buildProjects).toHaveBeenCalledWith(true, localDir, projectName);
		expect(convertAdmToJsZip).toHaveBeenCalledWith(mockZipBuffer);
		expect(createBuildZip).toHaveBeenCalledWith(mockConvertedBuffer, outputPath);
		expect(showSuccess).toHaveBeenCalledWith(BUILD_SUCCESSFUL);
		expect(showSuccess).toHaveBeenCalledWith(CREATED_BUILD_ZIP + outputPath);
		expect(showWarning).toHaveBeenCalledWith(IGNORE_PROJECT_ARG);
	});

	it('should call getOutputPath when output is not provided', async () => {
		const mockZipBuffer = Buffer.from('mockZipBuffer');
		const mockConvertedBuffer = Buffer.from('mockConvertedBuffer');
		const optionsWithoutOutput: BuildOptionsModel = { ...optionsWithNames, output: '' };

		(getOutputPath as jest.Mock).mockResolvedValue(outputPath);
		(buildAssets as jest.Mock).mockResolvedValue(mockZipBuffer);
		(convertAdmToJsZip as jest.Mock).mockResolvedValue(mockConvertedBuffer);

		await buildAction(projectName, optionsWithoutOutput);

		expect(getOutputPath).toHaveBeenCalledWith(projectName, optionsWithoutOutput.all, optionsWithoutOutput.names, 'build');
	});

	it('should not enable debug mode when debug is false', async () => {
		const optionsWithoutDebug: BuildOptionsModel = { ...optionsWithNames, debug: false };

		await buildAction(projectName, optionsWithoutDebug);

		expect(DebugManager.getInstance().setDebugEnabled).not.toHaveBeenCalled();
	});

	it('should handle errors and display an error message', async () => {
		const errorMessage = 'mock error message';
		(buildAssets as jest.Mock).mockRejectedValue(new Error(errorMessage));

		await expect(buildAction(projectName, optionsWithNames)).rejects.toThrow(errorMessage);
	});
});
