import * as yaml from 'js-yaml';
import { isYAML, loadYaml, loadMultiYaml, isYamlFile, isMultiYAML } from '../../src/functions/yaml.helper.js';

jest.mock('js-yaml', () => ({
    load: jest.fn(),
    dump: jest.fn(),
    loadAll: jest.fn()
}));

describe('YAML Helper Function tests', () => {
    describe('isYAML tests', () => {
        it('should return true for valid YAML data', () => {
            (yaml.dump as jest.Mock).mockReturnValue('key: value');
            (yaml.load as jest.Mock).mockReturnValue({ key: 'value' });
            expect(isYAML({ key: 'value' })).toBe(true);
        });

        it('should return false for invalid YAML data', () => {
            (yaml.dump as jest.Mock).mockReturnValue('invalid-yaml');
            (yaml.load as jest.Mock).mockImplementation(() => { throw new Error('Invalid YAML'); });
            expect(isYAML('invalid-yaml')).toBe(false);
        });
    });

    describe('loadYaml tests', () => {
        it('should parse valid YAML content correctly', () => {
            const yamlContent = 'key: value';
            const expectedOutput = { key: 'value' };
            (yaml.load as jest.Mock).mockReturnValue(expectedOutput);
            const result = loadYaml(yamlContent);
            expect(result).toEqual(expectedOutput);
            expect(yaml.load).toHaveBeenCalledWith(yamlContent);
        });

        it('should throw an error for invalid YAML content', () => {
            const invalidYamlContent = 'invalid-yaml';
            (yaml.load as jest.Mock).mockImplementation(() => { throw new Error('YAML parse error'); });
            expect(() => loadYaml(invalidYamlContent)).toThrow(Error);
            expect(() => loadYaml(invalidYamlContent)).toThrow('YAML parse error');
            expect(yaml.load).toHaveBeenCalledWith(invalidYamlContent);
        });

        it('should parse empty YAML content correctly', () => {
            const yamlContent = '';
            const expectedOutput = null;
            (yaml.load as jest.Mock).mockReturnValue(expectedOutput);
            const result = loadYaml(yamlContent);
            expect(result).toBe(expectedOutput);
            expect(yaml.load).toHaveBeenCalledWith(yamlContent);
        });
    });

    describe('isYamlFile tests', () => {
        it('should return true for a file with a .yaml extension', () => {
            const fileName = 'file.yaml';
            const result = isYamlFile(fileName);
            expect(result).toBe(true);
        });

        it('should return true for a file with a .yml extension', () => {
            const fileName = 'file.yml';
            const result = isYamlFile(fileName);
            expect(result).toBe(true);
        });

        it('should return false for a file with a different extension', () => {
            const fileName = 'file.json';
            const result = isYamlFile(fileName);
            expect(result).toBe(false);
        });

        it('should return false for a file name without an extension', () => {
            const fileName = 'file';
            const result = isYamlFile(fileName);
            expect(result).toBe(false);
        });

        it('should handle empty strings gracefully', () => {
            const fileName = '';
            const result = isYamlFile(fileName);
            expect(result).toBe(false);
        });
    });

    describe('loadMultiYaml tests', () => {
        it('should succesfully load all the provided file content', () => {
            const fileContent = `
            ---
            key1: value1
            ---
            key2: value2
            `;
            const parsedData = [{ key1: 'value1' }, { key2: 'value2' }];
            (yaml.loadAll as jest.Mock).mockReturnValue(parsedData);
            const result = loadMultiYaml(fileContent);
            expect(result).toEqual(parsedData);
            expect(yaml.loadAll).toHaveBeenCalledWith(fileContent);
        });

        it('should return an empty array if the YAML content is empty', () => {
            const fileContent = '';
            (yaml.loadAll as jest.Mock).mockReturnValue([]);
            const result = loadMultiYaml(fileContent);
            expect(yaml.loadAll).toHaveBeenCalledWith(fileContent);
            expect(result).toEqual([]);
        });

        it('should handle invalid YAML content gracefully', () => {
            const fileContent = 'invalid-yaml';
            (yaml.loadAll as jest.Mock).mockImplementation(() => {
                throw new Error('Invalid YAML');
            });
            expect(() => loadMultiYaml(fileContent)).toThrow('Invalid YAML');
            expect(yaml.loadAll).toHaveBeenCalledWith(fileContent);
        });

        it('should parse a single YAML document as an array', () => {
            const fileContent = `
            ---
            key: value
            `;
            const parsedData = [{ key: 'value' }];
            (yaml.loadAll as jest.Mock).mockReturnValue(parsedData);
            const result = loadMultiYaml(fileContent);
            expect(yaml.loadAll).toHaveBeenCalledWith(fileContent);
            expect(result).toEqual(parsedData);
        });
    });

    describe("isMultiYAML", () => {
        it("should return false for a single YAML document", () => {
          const yamlString = "key: value";
          require("js-yaml").loadAll.mockReturnValue([{ key: "value" }]);
          expect(isMultiYAML(yamlString)).toBe(false);
        });
      
        it("should return true for multiple YAML documents", () => {
          const yamlString = "---\nkey1: value1\n---\nkey2: value2";
          require("js-yaml").loadAll.mockReturnValue([
            { key1: "value1" },
            { key2: "value2" }
          ]);
          expect(isMultiYAML(yamlString)).toBe(true);
        });
      });
      
});