import { showInfo } from '../../helpers/common/message-helper.js';
import { getAllProjectNames } from '../../helpers/apim/root-dir-helper.js';
import { executeBuildProject } from '../../builders/project/projects-builder.js';
import { executeBuildProjectAssets } from '../../builders/project/project-assets-builder.js';
import { buildProjects, buildAssets, getOutputPath } from './build-action-helper.js';
import { BUILD_STARTED, BUILDING_LIST_ALL_PROJECTS, CHECKING_ALL_PROJECTS, IDENTIFIED_PROJECTS, LINE } from '../../constants/message-constants.js';
import { DebugManager } from '../../debug/debug-manager.js';
import { BUILD, TEST } from '../../constants/app-constants.js';


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

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

jest.mock('../../builders/project/projects-builder.js', () => ({
    executeBuildProject: jest.fn(),
}));

jest.mock('../../builders/project/project-assets-builder.js', () => ({
    executeBuildProjectAssets: jest.fn(),
}));

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

describe('Build-action-helper Test Suite', () => {
    beforeEach(() => {
        jest.clearAllMocks();
    });

    describe('buildProjects', () => {
        it('should handle empty projects list and call executeBuildProject', async () => {
            const all = false;
            const localDir = 'local/dir';
            const projects = '';

            (executeBuildProject as jest.Mock).mockResolvedValue(Buffer.from('zip-buffer'));

            await buildProjects(all, localDir, projects);

            expect(getAllProjectNames).not.toHaveBeenCalled();
            expect(executeBuildProject).toHaveBeenCalledWith(localDir, projects);
        });

        it('should call getAllProjectNames and executeBuildProject when DebugManager is not debug enabled', async () => {
            const all = true;
            const localDir = 'local/dir';
            const projects = 'project1,project2';
            const mockProjects = 'project1,project2';

            (DebugManager.getInstance as jest.Mock).mockReturnValue({
                isDebugEnabled: jest.fn().mockReturnValue(false),
            });
            (getAllProjectNames as jest.Mock).mockReturnValue(mockProjects);
            (executeBuildProject as jest.Mock).mockResolvedValue(Buffer.from('zip-buffer'));

            await buildProjects(all, localDir, projects);

            expect(showInfo).not.toHaveBeenCalledWith(BUILDING_LIST_ALL_PROJECTS + localDir);
            expect(showInfo).not.toHaveBeenCalledWith(CHECKING_ALL_PROJECTS + localDir);
            expect(showInfo).not.toHaveBeenCalledWith(IDENTIFIED_PROJECTS + mockProjects);
            expect(getAllProjectNames).toHaveBeenCalledWith(localDir);
            expect(executeBuildProject).toHaveBeenCalledWith(localDir, mockProjects);
        });
    });

    describe('buildAssets', () => {
        it('should handle empty assets string and call executeBuildProjectAssets', async () => {
            const assets = '';
            const localDir = 'local/dir';
            const projects = 'project1';

            (executeBuildProjectAssets as jest.Mock).mockResolvedValue(Buffer.from('zip-buffer'));

            await buildAssets(assets, localDir, projects);

            expect(showInfo).toHaveBeenCalledWith(LINE);
            expect(showInfo).toHaveBeenCalledWith(BUILD_STARTED);
            expect(showInfo).toHaveBeenCalledWith(LINE);
            expect(executeBuildProjectAssets).toHaveBeenCalledWith(projects, localDir, assets);
        });

        it('should handle projects containing commas and call executeBuildProjectAssets correctly', async () => {
            const assets = 'asset1,asset2';
            const localDir = 'local/dir';
            const projects = 'project1,project2';

            (executeBuildProjectAssets as jest.Mock).mockResolvedValue(Buffer.from('zip-buffer'));

            await buildAssets(assets, localDir, projects);

            expect(showInfo).toHaveBeenCalledWith(LINE);
            expect(showInfo).toHaveBeenCalledWith(BUILD_STARTED);
            expect(showInfo).toHaveBeenCalledWith(LINE);
            expect(executeBuildProjectAssets).toHaveBeenCalledWith(projects, localDir, assets);
        });
    });


    describe('getOutputPath', () => {
        it('should return default build zip file name when all is false and projects is undefined', async () => {
            const projects = undefined;
            const all = false;
            const names = 'name';
    
            const result = await getOutputPath(projects, all, names, BUILD);
    
            expect(result).toBe('studio-projects-build.zip');
        });
    
        it('should return default test zip file name when all is false and projects is undefined', async () => {
            const projects = undefined;
            const all = false;
            const names = 'name';
    
            const result = await getOutputPath(projects, all, names, TEST);
    
            expect(result).toBe('studio-projects-test.zip');
        });
    
        it('should return build zip file name for a single project when all is false and names is provided', async () => {
            const projects = 'project1';
            const all = false;
            const names = 'name';
    
            const result = await getOutputPath(projects, all, names, BUILD);
    
            expect(result).toBe('studio-project1-api-build.zip');
        });
    
        it('should return test zip file name for a single project when all is false and names is provided', async () => {
            const projects = 'project1';
            const all = false;
            const names = 'name';
    
            const result = await getOutputPath(projects, all, names, TEST);
    
            expect(result).toBe('studio-project1-api-test.zip');
        });
    
        it('should return build zip file name for a single project when all is false and names is not provided', async () => {
            const projects = 'project1';
            const all = false;
            const names = '';
    
            const result = await getOutputPath(projects, all, names, BUILD);
    
            expect(result).toBe('studio-project1-build.zip');
        });
    
        it('should return test zip file name for a single project when all is false and names is not provided', async () => {
            const projects = 'project1';
            const all = false;
            const names = '';
    
            const result = await getOutputPath(projects, all, names, TEST);
    
            expect(result).toBe('studio-project1-test.zip');
        });
    
        it('should return build zip file name for all projects when all is true', async () => {
            const projects = 'project1,project2';
            const all = true;
            const names = 'name';
    
            const result = await getOutputPath(projects, all, names, BUILD);
    
            expect(result).toBe('studio-all-build.zip');
        });
    
        it('should return test zip file name for all projects when all is true', async () => {
            const projects = 'project1,project2';
            const all = true;
            const names = 'name';
    
            const result = await getOutputPath(projects, all, names, TEST);
    
            expect(result).toBe('studio-all-test.zip');
        });
    
        it('should handle empty projects array correctly when all is false and return default build zip file name', async () => {
            const projects = '';
            const all = false;
            const names = 'name';
    
            const result = await getOutputPath(projects, all, names, BUILD);
    
            expect(result).toBe('studio-projects-build.zip');
        });
    
        it('should handle empty projects array correctly when all is false and return default test zip file name', async () => {
            const projects = '';
            const all = false;
            const names = 'name';
    
            const result = await getOutputPath(projects, all, names, TEST);
    
            expect(result).toBe('studio-projects-test.zip');
        });
    });
    
});