import createKubernetesApplyManifestAction from './k8s-apply';
import { KubeConfig, KubernetesObjectApi } from '@kubernetes/client-node';
import {
	createTemplateAction,
	TemplateAction,
} from '@backstage/plugin-scaffolder-backend';
import { JsonObject } from '@backstage/config';
import * as yaml from 'js-yaml';
import fs from 'fs';

jest.mock('fs');
jest.mock('@kubernetes/client-node', () => {
	const original = jest.requireActual('@kubernetes/client-node');
	return {
		...original,
		KubeConfig: jest.fn(),
		KubernetesObjectApi: {
			makeApiClient: jest.fn().mockReturnValue({
				create: jest.fn().mockResolvedValue({}),
			}),
		},
	};
});
jest.mock('js-yaml');

type ActionContext = {
	input: {
		manifestPath: string;
	};
	logger: {
		info: jest.Mock<any, any>;
		error: jest.Mock<any, any>;
	};
	logStream: {
		write: jest.Mock<any, any>;
	};
	workspacePath: string;
	output(name: string, value: any): void;
	createTemporaryDirectory(): Promise<string>;
};

describe('createKubernetesApplyManifestAction', () => {
	let action: TemplateAction<JsonObject>;

	beforeAll(() => {
		action = createKubernetesApplyManifestAction();
	});

	it('successfully applies a Kubernetes manifest from file', async () => {
		const mockContext: ActionContext = {
			input: {
				manifestPath: './manifests/pod.yaml',
			},
			logger: {
				info: jest.fn(),
				error: jest.fn(),
			},
			logStream: {
				write: jest.fn(),
			},
			workspacePath: '/tmp',
			output: jest.fn(),
			createTemporaryDirectory: jest
				.fn()
				.mockResolvedValue('/tmp/mock-temp-dir'),
		};

		// Mock fs to simulate reading a file
		fs.readFileSync.mockReturnValue('kind: Pod\nmetadata:\n  name: test-pod');

		// Mock yaml to simulate loading a Kubernetes object from the yaml content
		yaml.load.mockReturnValue({
			kind: 'Pod',
			metadata: { name: 'test-pod' },
		});

		await action.handler(mockContext);

		expect(KubernetesObjectApi.makeApiClient).toHaveBeenCalled();
		expect(mockContext.logger.info).toHaveBeenCalledWith(expect.any(String));
	});

	// Additional tests to cover error handling, invalid inputs, etc., can be added here.
});
