// helpers/executeOperation.ts
import { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
import { operations } from '../api/operations';
import { logger } from './logger';

/**
 * Execute the operation selected by the user
 *
 * @param this The n8n execution context
 * @returns Operation result as array of items
 */
export async function executeOperation(this: IExecuteFunctions): Promise<INodeExecutionData[]> {
	// Get parameters from the node
	const domain = this.getNodeParameter('domain', 0) as string;
	const resource = this.getNodeParameter('resource', 0) as string;
	const operation = this.getNodeParameter('operation', 0) as string;

	// Log the operation details
	logger.debug('executeOperation', `Executing ${domain}.${resource}.${operation}`, {
		domain,
		resource,
		operation,
	});

	// Validate if the domain exists
	if (!operations[domain]) {
		logger.error('executeOperation', `Domain "${domain}" not found`);
		throw new Error(`Domain "${domain}" not found`);
	}

	// Validate if the resource exists
	if (!operations[domain][resource]) {
		logger.error('executeOperation', `Resource "${resource}" not found in domain "${domain}"`);
		throw new Error(`Resource "${resource}" not found in domain "${domain}"`);
	}

	// Check if the operation exists and is a function
	if (!operations[domain][resource][operation]) {
		logger.error(
			'executeOperation',
			`Operation "${operation}" not found in resource "${resource}" of domain "${domain}"`,
		);
		throw new Error(
			`Operation "${operation}" not found in resource "${resource}" of domain "${domain}"`,
		);
	}

	if (typeof operations[domain][resource][operation] !== 'function') {
		logger.error(
			'executeOperation',
			`Operation "${operation}" in resource "${resource}" of domain "${domain}" is not a function`,
		);
		throw new Error(
			`Operation "${operation}" in resource "${resource}" of domain "${domain}" is not a function`,
		);
	}

	// Execute the operation
	try {
		logger.debug('executeOperation', `Calling ${domain}.${resource}.${operation}`);
		const result = await operations[domain][resource][operation].call(this);
		logger.debug('executeOperation', `Completed ${domain}.${resource}.${operation}`, {
			resultCount: result.length,
		});
		return result;
	} catch (error) {
		logger.error('executeOperation:error', error.message, { error });
		throw error;
	}
}
