/**
* Copyright Super iPaaS Integration LLC, an IBM Company 2024
*/
import { isValidAsset, hasNamespace, isValidAssetRefValue, getTargetModelAssetKind } from './asset-helper';
import { BaseAsset } from '../../model/assets-model';
import { isNullOrUndefined } from '../common/data-helper';
import { COLON, POLICY } from '../../constants/app-constants';
import { isPolicyKind } from './asset-kinds/policy-helper';

jest.mock('../common/data-helper');
jest.mock('./asset-kinds/policy-helper');

describe('asset-helper functions test suite', () => {
	beforeEach(() => {
		jest.clearAllMocks();
	});

	describe('isValidAsset', () => {
		it('should return false if asset is null or undefined', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValue(true);
			expect(isValidAsset(null as unknown as BaseAsset)).toBe(false);
			expect(isValidAsset(undefined as unknown as BaseAsset)).toBe(false);
		});

		it('should return false if asset.kind is null or undefined', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValueOnce(false).mockReturnValueOnce(true);
			const asset = { kind: null } as unknown as BaseAsset;
			expect(isValidAsset(asset)).toBe(false);
		});

		it('should return false if asset.metadata is null or undefined', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValueOnce(false).mockReturnValueOnce(false).mockReturnValueOnce(true);
			const asset = { kind: 'kind', metadata: null } as unknown as BaseAsset;
			expect(isValidAsset(asset)).toBe(false);
		});

		it('should return false if asset.metadata.name or asset.metadata.version is null or undefined', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValue(false).mockReturnValueOnce(false).mockReturnValueOnce(false).mockReturnValueOnce(true);
			const asset = { kind: 'kind', metadata: { name: null, version: '1.0' } } as unknown as BaseAsset;
			expect(isValidAsset(asset)).toBe(false);

			(isNullOrUndefined as jest.Mock).mockReturnValue(false).mockReturnValueOnce(false).mockReturnValueOnce(false).mockReturnValueOnce(false).mockReturnValueOnce(true);
			const assetWithVersionNull = { kind: 'kind', metadata: { name: 'name', version: null } } as unknown as BaseAsset;
			expect(isValidAsset(assetWithVersionNull)).toBe(false);
		});

		it('should return true for valid asset', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValue(false);
			const asset = { kind: 'kind', metadata: { name: 'name', version: '1.0' } } as unknown as BaseAsset;
			expect(isValidAsset(asset)).toBe(true);
		});
	});

	describe('isValidAssetRefValue', () => {
		it('should return false if assetRefValue is null or undefined', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValue(true);
			expect(isValidAssetRefValue(null as unknown as string)).toBe(false);
			expect(isValidAssetRefValue(undefined as unknown as string)).toBe(false);
		});
		it('should return true for valid assetRefValue with one or two parts separated by COLON', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValue(false);
			expect(isValidAssetRefValue(`valid${COLON}value`)).toBe(true);
			expect(isValidAssetRefValue('validOnlyOnePart')).toBe(true);
		});
		it('should return false if assetRefValue does not contain COLON', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValue(false);
			expect(isValidAssetRefValue('invalidRefValue')).toBe(true);
		});
	});

	describe('hasNamespace', () => {
		it('should return false if asset or asset.metadata is null or undefined', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValue(true);
			expect(hasNamespace(null as unknown as BaseAsset)).toBe(false);
			expect(hasNamespace({ metadata: null } as unknown as BaseAsset)).toBe(false);
		});

		it('should return false if asset.metadata.namespace is null or undefined', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValueOnce(false).mockReturnValueOnce(true);
			const asset = { metadata: { namespace: null } } as unknown as BaseAsset;
			expect(hasNamespace(asset)).toBe(false);
		});

		it('should return true if asset.metadata.namespace is defined', () => {
			(isNullOrUndefined as jest.Mock).mockReturnValue(false);
			const asset = { metadata: { namespace: 'namespace' } } as unknown as BaseAsset;
			expect(hasNamespace(asset)).toBe(true);
		});
		it('should return false if asset.metadata.namespace is undefined', () => {
			(isNullOrUndefined as jest.Mock).mockImplementation((value) => value === null || value === undefined);
			const asset: BaseAsset = { metadata: {} } as unknown as BaseAsset;
			expect(hasNamespace(asset)).toBe(false);
		});
	});


	describe('getTargetModelAssetKind', () => {
		it('should return POLICY if kind is a policy kind', () => {
			(isPolicyKind as jest.Mock).mockReturnValue(true);
			expect(getTargetModelAssetKind('somePolicyKind')).toBe(POLICY);
		});

		it('should return the original kind if it is not a policy kind', () => {
			(isPolicyKind as jest.Mock).mockReturnValue(false);
			expect(getTargetModelAssetKind('someOtherKind')).toBe('someOtherKind');
		});
	});
});
