import { IExecuteFunctions, IDataObject } from 'n8n-workflow';
import { apiRequest, apiRequestAllItems } from '../helpers/apiRequest';
import { handleProxMoxError } from '../helpers/errorHandler';
import { logger } from '../helpers/logger';

export async function executeClusterOperation(
	this: IExecuteFunctions,
	operation: string,
	i: number,
): Promise<IDataObject | IDataObject[]> {
	try {
		logger.operation('cluster', operation, 'start', { operation });

		let response: IDataObject | IDataObject[];

		switch (operation) {
			case 'getVersion':
				response = await getVersion.call(this);
				break;

			case 'getStatus':
				response = await getClusterStatus.call(this);
				break;

			case 'getResources':
				response = await getClusterResources.call(this, i);
				break;

			case 'getNodes':
				response = await getClusterNodes.call(this, i);
				break;

			case 'getTasks':
				response = await getClusterTasks.call(this, i);
				break;

			case 'getConfig':
				response = await getClusterConfig.call(this);
				break;

			default:
				throw new Error(`Unknown cluster operation: ${operation}`);
		}

		logger.operation('cluster', operation, 'success', { operation });
		return response;
	} catch (error) {
		logger.operation('cluster', operation, 'error', { operation, error: error.message });
		return handleProxMoxError.call(this, error, operation, 'cluster');
	}
}

async function getVersion(this: IExecuteFunctions): Promise<IDataObject> {
	logger.debug('cluster', 'Getting ProxMox VE version');
	return await apiRequest.call(this, 'GET', '/version');
}

async function getClusterStatus(this: IExecuteFunctions): Promise<IDataObject> {
	logger.debug('cluster', 'Getting cluster status');
	return await apiRequest.call(this, 'GET', '/cluster/status');
}

async function getClusterResources(this: IExecuteFunctions, i: number): Promise<IDataObject[]> {
	const returnAll = this.getNodeParameter('returnAll', i) as boolean;
	const resourceType = this.getNodeParameter('resourceType', i, '') as string;
	const additionalFields = this.getNodeParameter('additionalFields', i, {}) as IDataObject;

	let qs: IDataObject = {};

	if (resourceType) {
		qs.type = resourceType;
	}

	// Add additional filters
	if (additionalFields.node) {
		qs.node = additionalFields.node;
	}

	logger.debug('cluster', 'Getting cluster resources', { resourceType, additionalFields });

	if (returnAll) {
		return await apiRequestAllItems.call(this, 'GET', '/cluster/resources', {}, qs);
	} else {
		const limit = this.getNodeParameter('limit', i) as number;
		// ProxMox API doesn't support limit parameter, we'll slice the results client-side
		const response = await apiRequest.call(this, 'GET', '/cluster/resources', {}, qs);
		return Array.isArray(response) ? response.slice(0, limit) : [response];
	}
}

async function getClusterNodes(this: IExecuteFunctions, i: number): Promise<IDataObject[]> {
	const returnAll = this.getNodeParameter('returnAll', i) as boolean;

	logger.debug('cluster', 'Getting cluster nodes');

	if (returnAll) {
		return await apiRequestAllItems.call(this, 'GET', '/nodes', {});
	} else {
		const limit = this.getNodeParameter('limit', i) as number;
		// ProxMox API doesn't support limit parameter, we'll slice the results client-side
		const response = await apiRequest.call(this, 'GET', '/nodes', {});
		return Array.isArray(response) ? response.slice(0, limit) : [response];
	}
}

async function getClusterTasks(this: IExecuteFunctions, i: number): Promise<IDataObject[]> {
	const returnAll = this.getNodeParameter('returnAll', i) as boolean;
	const runningOnly = this.getNodeParameter('runningOnly', i, false) as boolean;
	const additionalFields = this.getNodeParameter('additionalFields', i, {}) as IDataObject;

	let qs: IDataObject = {};

	if (runningOnly) {
		qs.running = 1;
	}

	// Add additional filters
	if (additionalFields.node) {
		qs.node = additionalFields.node;
	}
	if (additionalFields.vmid) {
		qs.vmid = additionalFields.vmid;
	}
	if (additionalFields.user) {
		qs.user = additionalFields.user;
	}

	logger.debug('cluster', 'Getting cluster tasks', { runningOnly, additionalFields });

	if (returnAll) {
		return await apiRequestAllItems.call(this, 'GET', '/cluster/tasks', {}, qs);
	} else {
		const limit = this.getNodeParameter('limit', i) as number;
		// ProxMox API doesn't support limit parameter, we'll slice the results client-side
		const response = await apiRequest.call(this, 'GET', '/cluster/tasks', {}, qs);
		return Array.isArray(response) ? response.slice(0, limit) : [response];
	}
}

async function getClusterConfig(this: IExecuteFunctions): Promise<IDataObject> {
	logger.debug('cluster', 'Getting cluster configuration');
	return await apiRequest.call(this, 'GET', '/cluster/config');
}
