#!/usr/bin/env node

const { LoggerProxy, NodeHelpers } = require('n8n-workflow');
const { PackageDirectoryLoader } = require('../dist/DirectoryLoader');
const { packageDir, writeJSON } = require('./common');

LoggerProxy.init({
	log: console.log.bind(console),
	warn: console.warn.bind(console),
});

function findReferencedMethods(obj, refs = {}, latestName = '') {
	for (const key in obj) {
		if (key === 'name' && 'group' in obj) {
			latestName = obj[key];
		}

		if (typeof obj[key] === 'object') {
			findReferencedMethods(obj[key], refs, latestName);
		}

		if (key === 'loadOptionsMethod') {
			refs[latestName] = refs[latestName]
				? [...new Set([...refs[latestName], obj[key]])]
				: [obj[key]];
		}
	}

	return refs;
}

(async () => {
	const loader = new PackageDirectoryLoader(packageDir);
	await loader.loadAll();

	const credentialTypes = Object.values(loader.credentialTypes).map((data) => data.type);

	const loaderNodeTypes = Object.values(loader.nodeTypes);

	const definedMethods = loaderNodeTypes.reduce((acc, cur) => {
		NodeHelpers.getVersionedNodeTypeAll(cur.type).forEach((type) => {
			const methods = type.description?.__loadOptionsMethods;

			if (!methods) return;

			const { name } = type.description;

			if (acc[name]) {
				acc[name] = [...new Set([...acc[name], ...methods])];
				return;
			}

			acc[name] = methods;
		});

		return acc;
	}, {});

	const nodeTypes = loaderNodeTypes
		.map((data) => {
			const nodeType = NodeHelpers.getVersionedNodeType(data.type);
			NodeHelpers.applySpecialNodeParameters(nodeType);
			return data.type;
		})
		.flatMap((nodeData) => {
			return NodeHelpers.getVersionedNodeTypeAll(nodeData).map((item) => {
				const { __loadOptionsMethods, ...rest } = item.description;

				return rest;
			});
		});

	const referencedMethods = findReferencedMethods(nodeTypes);

	await Promise.all([
		writeJSON('types/credentials.json', credentialTypes),
		writeJSON('types/nodes.json', nodeTypes),
		writeJSON('methods/defined.json', definedMethods),
		writeJSON('methods/referenced.json', referencedMethods),
	]);
})();
