import { parseWorkflowCodeToBuilder } from './parse-workflow-code';

describe('parseWorkflowCodeToBuilder', () => {
	describe('SDK builder code', () => {
		it('should return a WorkflowBuilder from SDK workflow() calls', () => {
			const code = `export default workflow('test-id', 'My Workflow')
				.add(trigger({ type: 'n8n-nodes-base.manualTrigger', version: 1, config: {} }))
			`;

			const builder = parseWorkflowCodeToBuilder(code);

			expect(typeof builder.regenerateNodeIds).toBe('function');
			expect(typeof builder.validate).toBe('function');
			expect(typeof builder.toJSON).toBe('function');

			const json = builder.toJSON();
			expect(json.name).toBe('My Workflow');
			expect(json.nodes).toHaveLength(1);
		});

		it('should parse SDK code using nodeJson()', () => {
			const code = `
				const telegramTrigger = trigger({
					type: 'n8n-nodes-base.telegramTrigger',
					version: 1,
					config: { name: 'Telegram Trigger', parameters: {} }
				});
				const setChat = node({
					type: 'n8n-nodes-base.set',
					version: 3.4,
					config: {
						name: 'Set Chat',
						parameters: { chatId: nodeJson(telegramTrigger, 'message.chat.id') }
					}
				});
				export default workflow('test-id', 'My Workflow').add(telegramTrigger).to(setChat);
			`;

			const builder = parseWorkflowCodeToBuilder(code);
			const json = builder.toJSON();
			const setNode = json.nodes.find((node) => node.name === 'Set Chat');

			expect(setNode?.parameters?.chatId).toBe(
				"={{ $('Telegram Trigger').item.json.message.chat.id }}",
			);
		});
	});

	describe('plain object code (WorkflowJSON)', () => {
		it('should convert a plain object with nodes array into a WorkflowBuilder', () => {
			const code = `
				const myFlow = {
					name: 'TEST',
					nodes: [
						{
							id: 'sticky-test',
							name: 'Test Note',
							type: 'n8n-nodes-base.stickyNote',
							typeVersion: 1,
							position: [100, 100],
							parameters: { content: 'Hello', height: 200, width: 300, color: 3 }
						}
					],
					connections: {}
				};
				export default myFlow;
			`;

			const builder = parseWorkflowCodeToBuilder(code);

			expect(typeof builder.regenerateNodeIds).toBe('function');
			expect(typeof builder.validate).toBe('function');
			expect(typeof builder.toJSON).toBe('function');

			builder.regenerateNodeIds();
			const json = builder.toJSON();
			expect(json.name).toBe('TEST');
			expect(json.nodes).toHaveLength(1);
			expect(json.nodes[0].type).toBe('n8n-nodes-base.stickyNote');
		});

		it('should convert a directly exported object literal', () => {
			const code = `export default {
				name: 'Direct Export',
				nodes: [
					{
						id: 'node-1',
						name: 'Manual Trigger',
						type: 'n8n-nodes-base.manualTrigger',
						typeVersion: 1,
						position: [0, 0],
						parameters: {}
					}
				],
				connections: {}
			}`;

			const builder = parseWorkflowCodeToBuilder(code);
			builder.regenerateNodeIds();

			const json = builder.toJSON();
			expect(json.name).toBe('Direct Export');
			expect(json.nodes).toHaveLength(1);
		});

		it('should handle a plain object with multiple nodes', () => {
			const code = `export default {
				name: 'Multi Node',
				nodes: [
					{
						id: 'trigger-1',
						name: 'Manual Trigger',
						type: 'n8n-nodes-base.manualTrigger',
						typeVersion: 1,
						position: [0, 0],
						parameters: {}
					},
					{
						id: 'set-1',
						name: 'Set',
						type: 'n8n-nodes-base.set',
						typeVersion: 3.4,
						position: [200, 0],
						parameters: {}
					}
				],
				connections: {
					'Manual Trigger': {
						main: [[{ node: 'Set', type: 'main', index: 0 }]]
					}
				}
			}`;

			const builder = parseWorkflowCodeToBuilder(code);
			builder.regenerateNodeIds();

			const json = builder.toJSON();
			expect(json.nodes).toHaveLength(2);
			expect(json.connections).toBeDefined();
		});

		it('should handle a plain object with empty nodes array', () => {
			const code = "export default { name: 'Empty', nodes: [], connections: {} }";

			const builder = parseWorkflowCodeToBuilder(code);
			builder.regenerateNodeIds();

			const json = builder.toJSON();
			expect(json.name).toBe('Empty');
			expect(json.nodes).toHaveLength(0);
		});
	});

	describe('invalid exports', () => {
		it('should throw for a number export', () => {
			expect(() => parseWorkflowCodeToBuilder('export default 42')).toThrow(
				'Code must export a workflow built with the workflow() SDK function.',
			);
		});

		it('should throw for a string export', () => {
			expect(() => parseWorkflowCodeToBuilder("export default 'hello'")).toThrow(
				'Code must export a workflow built with the workflow() SDK function.',
			);
		});

		it('should throw for an object without nodes', () => {
			expect(() => parseWorkflowCodeToBuilder("export default { foo: 'bar' }")).toThrow(
				'Code must export a workflow built with the workflow() SDK function.',
			);
		});

		it('should throw for a boolean export', () => {
			expect(() => parseWorkflowCodeToBuilder('export default true')).toThrow(
				'Code must export a workflow built with the workflow() SDK function.',
			);
		});
	});
});
