import { createKubernetesApplyManifestAction } from './createKubernetesApplyManifestAction';
import { KubeConfig, KubernetesObjectApi } from '@kubernetes/client-node';
import * as yaml from 'js-yaml';
import fs from 'fs';

// Mocking fs to simulate file reading
jest.mock('fs');

// Setup for KubernetesObjectApi and yaml mocks remains the same
jest.mock('@kubernetes/client-node', () => {
	const originalModule = jest.requireActual('@kubernetes/client-node');
	return {
		...originalModule,
		KubeConfig: jest.fn(),
		KubernetesObjectApi: {
			makeApiClient: jest.fn().mockReturnValue({
				create: jest.fn(),
			}),
		},
	};
});
jest.mock('js-yaml');

describe('createKubernetesApplyManifestAction', () => {
	const originalEnv = process.env;
	beforeEach(() => {
		jest.resetModules(); // Resets module registry to clear cache
		process.env = { ...originalEnv }; // Make a copy of the environment
	});

	afterAll(() => {
		process.env = originalEnv; // Restore original environment
	});

	it('successfully applies a Kubernetes manifest from file', async () => {
		process.env.TOKEN = 'fake-token';
		process.env.CLUSTER_URL = 'https://example.com';
		fs.readFileSync.mockReturnValue('valid-manifest-content');
		yaml.load.mockReturnValue({ kind: 'Pod', metadata: { name: 'test-pod' } });

		const action = createKubernetesApplyManifestAction();
		const mockContext = {
			input: {
				manifestPath: './manifests/pod.yaml',
			},
			logger: {
				info: jest.fn(),
				error: jest.fn(),
			},
		};

		await action.handler(mockContext);

		expect(fs.readFileSync).toHaveBeenCalledWith(
			expect.stringContaining('pod.yaml'),
			'utf8'
		);
		expect(yaml.load).toHaveBeenCalledWith('valid-manifest-content');
		expect(KubernetesObjectApi.makeApiClient().create).toHaveBeenCalled();
		expect(mockContext.logger.info).toHaveBeenCalledWith(
			expect.stringContaining('Successfully applied manifest for Pod/test-pod')
		);
	});

	it('throws an error when TOKEN or CLUSTER_URL environment variables are missing', async () => {
		// Clearing environment variables to simulate missing configuration
		delete process.env.TOKEN;
		delete process.env.CLUSTER_URL;

		const action = createKubernetesApplyManifestAction();
		const mockContext = {
			input: {
				manifestPath: './manifests/pod.yaml',
			},
			logger: {
				info: jest.fn(),
				error: jest.fn(),
			},
		};

		await expect(action.handler(mockContext)).rejects.toThrow(
			'Missing required environment variables: TOKEN or CLUSTER_URL'
		);
	});

	it('throws an error for an invalid manifest file', async () => {
		process.env.TOKEN = 'fake-token';
		process.env.CLUSTER_URL = 'https://example.com';
		fs.readFileSync.mockReturnValue('invalid-manifest-content');
		yaml.load.mockReturnValue(null); // Simulating invalid YAML content

		const action = createKubernetesApplyManifestAction();
		const mockContext = {
			input: {
				manifestPath: './manifests/pod.yaml',
			},
			logger: {
				info: jest.fn(),
				error: jest.fn(),
			},
		};

		await expect(action.handler(mockContext)).rejects.toThrow(
			'Invalid manifest: must be a valid YAML or JSON object'
		);
	});
});
