/**
* Copyright Super iPaaS Integration LLC, an IBM Company 2024
*/
import { getRefsFromTestAsset } from './test-kind-helper.js';
import { BaseAsset } from '../../../model/assets-model.js';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { showError } from '../../common/message-helper.js';

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

describe('getRefsFromTestAsset', () => {
	beforeEach(() => {
		jest.clearAllMocks();
	});
	it('should return AssetCacheModel with environment ref', () => {
		const testAsset: BaseAsset = {
			spec: {
				'environment': { $ref: 'dev:env-ref:1.0' },
				request: [],
			},
		} as unknown as BaseAsset;

		const result = getRefsFromTestAsset(testAsset);

		expect(result).toEqual([
			{ kind: 'Environment', ref: 'dev:env-ref:1.0', isNewlyAdded: true },
		]);
	});

	it('should return AssetCacheModel with assertions refs', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: { $ref: 'dev:env-ref:1.0' },
				request: [
					{ assertions: { $ref: 'dev:assertion-ref-1:2.0' } },
					{ assertions: { $ref: 'dev:assertion-ref-2:3.0' } },
				],
			}
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Environment', ref: 'dev:env-ref:1.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-1:2.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-2:3.0', isNewlyAdded: true },
		]);

	});
	it('should handle a missing environment or assertion refs', () => {
		const testAsset: BaseAsset = {
			spec: {
				request: [
					{ assertions: {} },
					{ assertions: { $ref: 'dev:assertion-ref-1:2.0' } },
				],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Assertion', ref: 'dev:assertion-ref-1:2.0', isNewlyAdded: true },
		]);
	});
	it('should handle cases where request is undefined or null', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: { $ref: 'dev:env-ref:1.0' },
				request: null,
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([{ kind: 'Environment', ref: 'dev:env-ref:1.0', isNewlyAdded: true }]);
	});

	it('should handle cases where assertions are undefined or null', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: { $ref: 'dev:env-ref:1.0' },
				request: [{ assertions: null }],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([{ kind: 'Environment', ref: 'dev:env-ref:1.0', isNewlyAdded: true }]);
	});

	it('should handle cases where environment are undefined or null', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: null,
				request: [{ assertions: { $ref: 'dev:assertion-ref-1:2.0' } }],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([{ kind: 'Assertion', ref: 'dev:assertion-ref-1:2.0', isNewlyAdded: true }]);
	});

	it('should return empty array when there are no refs', () => {
		const testAsset: BaseAsset = {
			spec: {
				'environment': {},
				request: [],
			},
		} as unknown as BaseAsset;

		const result = getRefsFromTestAsset(testAsset);

		expect(result).toEqual([]);
	});

	it('should handle test asset with missing spec properties', () => {
		const testAsset: BaseAsset = {
			spec: {},
		} as unknown as BaseAsset;

		const result = getRefsFromTestAsset(testAsset);

		expect(result).toEqual([]);
	});

	it('should handle empty environment and run the request with multiple request', () => {
		// Since $ref should be a string, we'll use an empty object for environment
		const testAsset: BaseAsset = {
			spec: {
				environment: {},
				request: [
					{ assertions: { $ref: 'dev:assertion-ref-1:2.0' } },
				],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Assertion', ref: 'dev:assertion-ref-1:2.0', isNewlyAdded: true }
		]);
	});


	it('should handle errors and call showError', () => {
		const mockShowError = jest.fn();
		(showError as jest.Mock) = mockShowError;
		const faultyAsset: BaseAsset = {
			spec: undefined,
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(faultyAsset);
		expect(mockShowError).toHaveBeenCalledWith(expect.stringContaining('Cannot read properties of undefined (reading \'environment\')'));
		expect(result).toEqual([]);
	});

	it('should handle multiple assertions with individual $ref properties', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: { $ref: 'dev:env-ref:1.0' },
				request: [
					{
						assertions: [
							{ $ref: 'dev:assertion-ref-1:2.0' },
							{ $ref: 'dev:assertion-ref-2:3.0' }
						]
					},
				],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Environment', ref: 'dev:env-ref:1.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-1:2.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-2:3.0', isNewlyAdded: true },
		]);
	});

	it('should handle multiple assertions across different requests', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: { $ref: 'dev:env-ref:1.0' },
				request: [
					{
						assertions: [
							{ $ref: 'dev:assertion-ref-1:2.0' },
							{ $ref: 'dev:assertion-ref-2:3.0' }
						]
					},
					{
						assertions: [
							{ $ref: 'dev:assertion-ref-3:4.0' },
							{ $ref: 'dev:assertion-ref-4:5.0' }
						]
					},
				],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Environment', ref: 'dev:env-ref:1.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-1:2.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-2:3.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-3:4.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-4:5.0', isNewlyAdded: true },
		]);
	});

	it('should handle a mix of single assertion with direct $ref and multiple assertions with individual $ref properties', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: { $ref: 'dev:env-ref:1.0' },
				request: [
					{ assertions: { $ref: 'dev:assertion-ref-1:2.0' } },
					{
						assertions: [
							{ $ref: 'dev:assertion-ref-2:3.0' },
							{ $ref: 'dev:assertion-ref-3:4.0' }
						]
					},
				],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Environment', ref: 'dev:env-ref:1.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-1:2.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-2:3.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-3:4.0', isNewlyAdded: true },
		]);
	});

	it('should handle empty array of assertions', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: { $ref: 'dev:env-ref:1.0' },
				request: [
					{ assertions: [] },
				],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Environment', ref: 'dev:env-ref:1.0', isNewlyAdded: true },
		]);
	});

	it('should handle multiple environment references with individual $ref properties', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: [
					{ $ref: 'dev:env-ref-1:1.0' },
					{ $ref: 'dev:env-ref-2:2.0' }
				],
				request: [],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Environment', ref: 'dev:env-ref-1:1.0', isNewlyAdded: true },
			{ kind: 'Environment', ref: 'dev:env-ref-2:2.0', isNewlyAdded: true },
		]);
	});

	it('should handle both environment and assertion references in multiple formats', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: [
					{ $ref: 'dev:env-ref-1:1.0' },
					{ $ref: 'dev:env-ref-2:2.0' }
				],
				request: [
					{ assertions: { $ref: 'dev:assertion-ref-1:2.0' } },
					{
						assertions: [
							{ $ref: 'dev:assertion-ref-2:3.0' },
							{ $ref: 'dev:assertion-ref-3:4.0' }
						]
					},
				],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Environment', ref: 'dev:env-ref-1:1.0', isNewlyAdded: true },
			{ kind: 'Environment', ref: 'dev:env-ref-2:2.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-1:2.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-2:3.0', isNewlyAdded: true },
			{ kind: 'Assertion', ref: 'dev:assertion-ref-3:4.0', isNewlyAdded: true },
		]);
	});

	it('should handle empty array of environment references', () => {
		const testAsset: BaseAsset = {
			spec: {
				environment: [],
				request: [
					{ assertions: { $ref: 'dev:assertion-ref-1:2.0' } },
				],
			},
		} as unknown as BaseAsset;
		const result = getRefsFromTestAsset(testAsset);
		expect(result).toEqual([
			{ kind: 'Assertion', ref: 'dev:assertion-ref-1:2.0', isNewlyAdded: true },
		]);
	});
});
