import { BaseAsset } from "@apic/studio-client-model";
import { isBaseAsset, isValidAsset, isValidAssetRefValue } from "../../src/functions/asset.helper.js";
import { isNullOrUndefined } from "../../src/functions/data.helper.js";
import { getDocumentBasedOnLanguage } from "../../src/functions/data.parser.js";



jest.mock('../../src/functions/data.parser', () => ({
    getDocumentBasedOnLanguage: jest.fn(),
}));

jest.mock('../../src/functions/data.helper', () => ({
    isNullOrUndefined: jest.fn(),
}));

jest.mock('@apic/api-model/common/StudioEnums', () => ({
    KindEnums: {
        VALUE_ONE: "mocked_value_one",
        VALUE_TWO: "mocked_value_two",
    },
}));

describe('Asset Helper Functions test', () => {
    const mockGetDocumentBasedOnLanguage = getDocumentBasedOnLanguage as jest.Mock;
    const mockIsNullOrUndefined = isNullOrUndefined as jest.Mock;

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

    describe('isBaseAsset', () => {
        it('should return true when parsedYaml.kind exists', () => {
            const fileContent = 'foo : bar';
            const language = 'yaml';
            mockGetDocumentBasedOnLanguage.mockReturnValue({ kind: 'BaseAsset' });
            const result = isBaseAsset(fileContent, language);
            expect(result).toBe(true);
            expect(mockGetDocumentBasedOnLanguage).toHaveBeenCalledWith(fileContent, language);
        });

        it('should return false when parsedYaml.kind is missing', () => {
            const fileContent = 'foo : bar';
            const language = 'yaml';
            mockGetDocumentBasedOnLanguage.mockReturnValue({});
            const result = isBaseAsset(fileContent, language);
            expect(result).toBe(false);
            expect(mockGetDocumentBasedOnLanguage).toHaveBeenCalledWith(fileContent, language);
        });

        it('should return false when parsedYaml is null', () => {
            const fileContent = 'foo : bar';
            const language = 'yaml';
            mockGetDocumentBasedOnLanguage.mockReturnValue(null);
            const result = isBaseAsset(fileContent, language);
            expect(result).toBe(false);
            expect(mockGetDocumentBasedOnLanguage).toHaveBeenCalledWith(fileContent, language);
        });

        it('should throw an error if getDocumentBasedOnLanguage throws an error', () => {
            const fileContent = 'dummy-content';
            const language = 'yaml';
            mockGetDocumentBasedOnLanguage.mockImplementation(() => {
                throw new Error('Parsing error');
            });
            expect(() => isBaseAsset(fileContent, language)).toThrow('Parsing error');
            expect(mockGetDocumentBasedOnLanguage).toHaveBeenCalledWith(fileContent, language);
        });
    });

    describe('isValidAsset', () => {

        it('should return true if the asset is valid (not null or undefined)', () => {
            mockIsNullOrUndefined.mockReturnValue(false);
            const asset = { kind: 'BaseAsset', metadata: { name: 'assetName' } } as BaseAsset;
            const result = isValidAsset(asset, false);
            expect(result).toBeTruthy();
            expect(mockIsNullOrUndefined).toHaveBeenCalledWith(asset);
        });
    });

    describe('isValidAssetRefValue', () => {

        it('should return true if assetRefValue contains one colon-separated part', () => {
            mockIsNullOrUndefined.mockReturnValue(false);
            const assetRefValue = 'value1';
            const result = isValidAssetRefValue(assetRefValue);
            expect(result).toBe(true);
            expect(mockIsNullOrUndefined).toHaveBeenCalledWith(assetRefValue);
        });

        it('should return true if assetRefValue contains three colon-separated parts', () => {
            mockIsNullOrUndefined.mockReturnValue(false);
            const assetRefValue = 'value1:value2:value3';
            const result = isValidAssetRefValue(assetRefValue);
            expect(result).toBe(true);
            expect(mockIsNullOrUndefined).toHaveBeenCalledWith(assetRefValue);
        });

        it('should return false if assetRefValue contains more than three colon-separated parts', () => {
            mockIsNullOrUndefined.mockReturnValue(false);
            const assetRefValue = 'value1:value2:value3:value4';
            const result = isValidAssetRefValue(assetRefValue);
            expect(result).toBe(false);
            expect(mockIsNullOrUndefined).toHaveBeenCalledWith(assetRefValue);
        });

        it('should return false if assetRefValue contains no colon-separated parts', () => {
            mockIsNullOrUndefined.mockReturnValue(false);
            const assetRefValue = '';
            const result = isValidAssetRefValue(assetRefValue);
            expect(result).toBe(true);
            expect(mockIsNullOrUndefined).toHaveBeenCalledWith(assetRefValue);
        });
    });
});
