import type { IExecuteFunctions, IBinaryData } from 'n8n-workflow';
import { mockDeep } from 'vitest-mock-extended';

import * as helpers from '@utils/helpers';

import * as file from './actions/file';
import * as image from './actions/image';
import * as prompt from './actions/prompt';
import * as text from './actions/text';
import type { File } from './helpers/interfaces';
import * as utils from './helpers/utils';
import * as transport from './transport';

describe('Anthropic Node', () => {
	const executeFunctionsMock = mockDeep<IExecuteFunctions>();
	const apiRequestMock = vi.spyOn(transport, 'apiRequest');
	const getConnectedToolsMock = vi.spyOn(helpers, 'getConnectedTools');
	const downloadFileMock = vi.spyOn(utils, 'downloadFile');
	const uploadFileMock = vi.spyOn(utils, 'uploadFile');
	const getBaseUrlMock = vi.spyOn(utils, 'getBaseUrl');

	beforeEach(() => {
		vi.resetAllMocks();
	});

	describe('Text -> Message', () => {
		it('should call the api with the correct parameters', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'messages.values':
						return [{ role: 'user', content: 'Hello, world!' }];
					case 'simplify':
						return true;
					case 'addAttachments':
						return false;
					case 'options':
						return {
							system: 'You are a helpful assistant.',
							codeExecution: true,
							webSearch: true,
							allowedDomains: 'https://example.com',
							maxTokens: 1024,
							temperature: 0.7,
							topP: 0.9,
							topK: 40,
						};
					default:
						return undefined;
				}
			});
			executeFunctionsMock.getNodeInputs.mockReturnValue([{ type: 'main' }, { type: 'ai_tool' }]);
			getConnectedToolsMock.mockResolvedValue([]);
			apiRequestMock.mockResolvedValue({
				content: [{ type: 'text', text: 'Hello! How can I help you today?' }],
				stop_reason: 'end_turn',
			});

			const result = await text.message.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						content: [
							{
								type: 'text',
								text: 'Hello! How can I help you today?',
							},
						],
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(apiRequestMock).toHaveBeenCalledWith('POST', '/v1/messages', {
				body: {
					model: 'claude-sonnet-4-20250514',
					max_tokens: 1024,
					temperature: 0.7,
					top_p: 0.9,
					top_k: 40,
					system: 'You are a helpful assistant.',
					messages: [
						{
							role: 'user',
							content: 'Hello, world!',
						},
					],
					tools: [
						{
							type: 'code_execution_20250522',
							name: 'code_execution',
						},
						{
							type: 'web_search_20250305',
							name: 'web_search',
							allowed_domains: ['https://example.com'],
						},
					],
				},
				enableAnthropicBetas: {
					codeExecution: true,
				},
			});
		});

		it('should add code execution attachments', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'messages.values':
						return [{ role: 'user', content: 'Hello, world!' }];
					case 'simplify':
						return true;
					case 'addAttachments':
						return true;
					case 'attachmentsInputType':
						return 'url';
					case 'attachmentsUrls':
						return 'https://example.com/file.pdf';
					case 'options':
						return {
							codeExecution: true,
						};
					default:
						return undefined;
				}
			});
			executeFunctionsMock.getNodeInputs.mockReturnValue([{ type: 'main' }, { type: 'ai_tool' }]);
			getBaseUrlMock.mockResolvedValue('https://api.anthropic.com');
			downloadFileMock.mockResolvedValue({
				fileContent: Buffer.from('abcdefgh'),
				mimeType: 'application/pdf',
			});
			uploadFileMock.mockResolvedValue({
				id: 'file_123',
			} as File);
			getConnectedToolsMock.mockResolvedValue([]);
			apiRequestMock.mockResolvedValue({
				content: [{ type: 'text', text: 'Hello! How can I help you today?' }],
				stop_reason: 'end_turn',
			});

			const result = await text.message.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						content: [
							{
								type: 'text',
								text: 'Hello! How can I help you today?',
							},
						],
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(downloadFileMock).toHaveBeenCalledWith('https://example.com/file.pdf');
			expect(uploadFileMock).toHaveBeenCalledWith(Buffer.from('abcdefgh'), 'application/pdf');
			expect(apiRequestMock).toHaveBeenCalledWith('POST', '/v1/messages', {
				body: {
					model: 'claude-sonnet-4-20250514',
					max_tokens: 1024,
					messages: [
						{
							role: 'user',
							content: 'Hello, world!',
						},
						{
							role: 'user',
							content: [
								{
									type: 'container_upload',
									file_id: 'file_123',
								},
							],
						},
					],
					tools: [
						{
							type: 'code_execution_20250522',
							name: 'code_execution',
						},
					],
				},
				enableAnthropicBetas: {
					codeExecution: true,
				},
			});
		});

		it('should add regular attachments', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'messages.values':
						return [{ role: 'user', content: 'Hello, world!' }];
					case 'simplify':
						return true;
					case 'addAttachments':
						return true;
					case 'attachmentsInputType':
						return 'url';
					case 'attachmentsUrls':
						return 'https://example.com/file.pdf';
					case 'options':
						return {};
					default:
						return undefined;
				}
			});
			executeFunctionsMock.getNodeInputs.mockReturnValue([{ type: 'main' }, { type: 'ai_tool' }]);
			getBaseUrlMock.mockResolvedValue('https://api.anthropic.com');
			executeFunctionsMock.helpers.httpRequest.mockResolvedValue({
				headers: {
					'content-type': 'application/pdf',
				},
			});
			getConnectedToolsMock.mockResolvedValue([]);
			apiRequestMock.mockResolvedValue({
				content: [{ type: 'text', text: 'Hello! How can I help you today?' }],
				stop_reason: 'end_turn',
			});

			const result = await text.message.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						content: [
							{
								type: 'text',
								text: 'Hello! How can I help you today?',
							},
						],
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(executeFunctionsMock.helpers.httpRequest).toHaveBeenCalledWith({
				method: 'HEAD',
				url: 'https://example.com/file.pdf',
				returnFullResponse: true,
			});
			expect(apiRequestMock).toHaveBeenCalledWith('POST', '/v1/messages', {
				body: {
					model: 'claude-sonnet-4-20250514',
					max_tokens: 1024,
					messages: [
						{
							role: 'user',
							content: 'Hello, world!',
						},
						{
							role: 'user',
							content: [
								{
									type: 'document',
									source: {
										type: 'url',
										url: 'https://example.com/file.pdf',
									},
								},
							],
						},
					],
					tools: [],
				},
				enableAnthropicBetas: {},
			});
		});
	});

	describe('Empty Prompt Validation', () => {
		it('should throw error when text messages are all empty without attachments', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'messages.values':
						return [{ role: 'user', content: '' }];
					case 'addAttachments':
						return false;
					case 'simplify':
						return true;
					case 'options':
						return {};
					default:
						return undefined;
				}
			});

			await expect(text.message.execute.call(executeFunctionsMock, 0)).rejects.toThrow(
				'A non-empty prompt is required.',
			);
		});

		it('should throw error when text messages are whitespace-only without attachments', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'messages.values':
						return [{ role: 'user', content: '   ' }];
					case 'addAttachments':
						return false;
					case 'simplify':
						return true;
					case 'options':
						return {};
					default:
						return undefined;
				}
			});

			await expect(text.message.execute.call(executeFunctionsMock, 0)).rejects.toThrow(
				'A non-empty prompt is required.',
			);
		});

		it('should NOT throw for empty messages when attachments are enabled', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'messages.values':
						return [{ role: 'user', content: '' }];
					case 'addAttachments':
						return true;
					case 'attachmentsInputType':
						return 'url';
					case 'attachmentsUrls':
						return 'https://example.com/file.pdf';
					case 'simplify':
						return true;
					case 'options':
						return {};
					default:
						return undefined;
				}
			});
			executeFunctionsMock.getNodeInputs.mockReturnValue([{ type: 'main' }]);
			getBaseUrlMock.mockResolvedValue('https://api.anthropic.com');
			executeFunctionsMock.helpers.httpRequest.mockResolvedValue({
				headers: { 'content-type': 'application/pdf' },
			});
			getConnectedToolsMock.mockResolvedValue([]);
			apiRequestMock.mockResolvedValue({
				content: [{ type: 'text', text: 'Response' }],
				stop_reason: 'end_turn',
			});

			await expect(text.message.execute.call(executeFunctionsMock, 0)).resolves.toBeDefined();
		});

		it('should throw error when image analyze text is empty', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'inputType':
						return 'url';
					case 'imageUrls':
						return 'https://example.com/image.png';
					case 'text':
						return '';
					case 'simplify':
						return true;
					case 'options':
						return {};
					default:
						return undefined;
				}
			});

			await expect(image.analyze.execute.call(executeFunctionsMock, 0)).rejects.toThrow(
				'A non-empty prompt is required.',
			);
		});
	});

	describe('File -> Upload', () => {
		it('should upload file from URL', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'inputType':
						return 'url';
					case 'fileUrl':
						return 'https://example.com/file.pdf';
					case 'options.fileName':
						return 'test.pdf';
					default:
						return undefined;
				}
			});
			getBaseUrlMock.mockResolvedValue('https://api.anthropic.com');
			downloadFileMock.mockResolvedValue({
				fileContent: Buffer.from('test file content'),
				mimeType: 'application/pdf',
			});
			uploadFileMock.mockResolvedValue({
				created_at: '2025-01-01T10:00:00Z',
				downloadable: true,
				filename: 'test.pdf',
				id: 'file_123',
				mime_type: 'application/pdf',
				size_bytes: 17,
				type: 'file',
			});

			const result = await file.upload.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						created_at: '2025-01-01T10:00:00Z',
						downloadable: true,
						filename: 'test.pdf',
						id: 'file_123',
						mime_type: 'application/pdf',
						size_bytes: 17,
						type: 'file',
						url: 'https://api.anthropic.com/v1/files/file_123',
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(downloadFileMock).toHaveBeenCalledWith('https://example.com/file.pdf');
			expect(uploadFileMock).toHaveBeenCalledWith(
				Buffer.from('test file content'),
				'application/pdf',
				'test.pdf',
			);
		});

		it('should upload file from binary data', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'inputType':
						return 'binary';
					case 'binaryPropertyName':
						return 'data';
					case 'options.fileName':
						return 'file';
					default:
						return undefined;
				}
			});
			getBaseUrlMock.mockResolvedValue('https://api.anthropic.com');
			const mockBinaryData: IBinaryData = {
				mimeType: 'application/pdf',
				fileName: 'test.pdf',
				fileSize: '1024',
				fileExtension: 'pdf',
				data: 'test',
			};
			executeFunctionsMock.helpers.assertBinaryData.mockReturnValue(mockBinaryData);
			executeFunctionsMock.helpers.getBinaryDataBuffer.mockResolvedValue(
				Buffer.from('test file content'),
			);
			uploadFileMock.mockResolvedValue({
				created_at: '2025-01-01T10:00:00Z',
				downloadable: true,
				filename: 'file',
				id: 'file_456',
				mime_type: 'application/pdf',
				size_bytes: 17,
				type: 'file',
			});

			const result = await file.upload.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						created_at: '2025-01-01T10:00:00Z',
						downloadable: true,
						filename: 'file',
						id: 'file_456',
						mime_type: 'application/pdf',
						size_bytes: 17,
						type: 'file',
						url: 'https://api.anthropic.com/v1/files/file_456',
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(uploadFileMock).toHaveBeenCalledWith(
				Buffer.from('test file content'),
				'application/pdf',
				'file',
			);
		});
	});

	describe('File -> List', () => {
		it('should list files with a limit', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'returnAll':
						return false;
					case 'limit':
						return 10;
					default:
						return undefined;
				}
			});
			getBaseUrlMock.mockResolvedValue('https://api.anthropic.com');
			apiRequestMock.mockResolvedValue({
				data: [
					{
						id: 'file_123',
						filename: 'test.pdf',
						mime_type: 'application/pdf',
					},
					{
						id: 'file_456',
						filename: 'test.png',
						mime_type: 'image/png',
					},
				],
				first_id: '',
				last_id: '',
				has_more: false,
			});

			const result = await file.list.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						id: 'file_123',
						filename: 'test.pdf',
						mime_type: 'application/pdf',
						url: 'https://api.anthropic.com/v1/files/file_123',
					},
					pairedItem: { item: 0 },
				},
				{
					json: {
						id: 'file_456',
						filename: 'test.png',
						mime_type: 'image/png',
						url: 'https://api.anthropic.com/v1/files/file_456',
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(apiRequestMock).toHaveBeenCalledWith('GET', '/v1/files', {
				qs: {
					limit: 10,
				},
			});
		});

		it('should list all files', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'returnAll':
						return true;
					default:
						return undefined;
				}
			});
			getBaseUrlMock.mockResolvedValue('https://api.anthropic.com');
			apiRequestMock.mockResolvedValueOnce({
				data: [
					{
						id: 'file_001',
						filename: 'test-1.pdf',
						mime_type: 'application/pdf',
					},
					{
						id: 'file_002',
						filename: 'test-2.pdf',
						mime_type: 'application/pdf',
					},
				],
				first_id: 'file_001',
				last_id: 'file_002',
				has_more: true,
			});
			apiRequestMock.mockResolvedValueOnce({
				data: [
					{
						id: 'file_003',
						filename: 'test-3.pdf',
						mime_type: 'application/pdf',
					},
				],
				first_id: 'file_003',
				last_id: 'file_003',
				has_more: false,
			});

			const result = await file.list.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						id: 'file_001',
						filename: 'test-1.pdf',
						mime_type: 'application/pdf',
						url: 'https://api.anthropic.com/v1/files/file_001',
					},
					pairedItem: { item: 0 },
				},
				{
					json: {
						id: 'file_002',
						filename: 'test-2.pdf',
						mime_type: 'application/pdf',
						url: 'https://api.anthropic.com/v1/files/file_002',
					},
					pairedItem: { item: 0 },
				},
				{
					json: {
						id: 'file_003',
						filename: 'test-3.pdf',
						mime_type: 'application/pdf',
						url: 'https://api.anthropic.com/v1/files/file_003',
					},
					pairedItem: { item: 0 },
				},
			]);
		});
	});

	describe('File -> Delete', () => {
		it('should delete file', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'fileId':
						return 'file_123';
					default:
						return undefined;
				}
			});
			apiRequestMock.mockResolvedValue({
				id: 'file_123',
			});

			const result = await file.deleteFile.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([{ json: { id: 'file_123' }, pairedItem: { item: 0 } }]);
			expect(apiRequestMock).toHaveBeenCalledWith('DELETE', '/v1/files/file_123');
		});
	});

	describe('File -> Get', () => {
		it('should get file', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'fileId':
						return 'file_123';
					default:
						return undefined;
				}
			});
			getBaseUrlMock.mockResolvedValue('https://api.anthropic.com');
			apiRequestMock.mockResolvedValue({
				id: 'file_123',
				filename: 'test.pdf',
				mime_type: 'application/pdf',
			});

			const result = await file.get.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						id: 'file_123',
						filename: 'test.pdf',
						mime_type: 'application/pdf',
						url: 'https://api.anthropic.com/v1/files/file_123',
					},
					pairedItem: { item: 0 },
				},
			]);
		});
	});

	describe('Image -> Analyze', () => {
		it('should analyze image from URL', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'inputType':
						return 'url';
					case 'imageUrls':
						return 'https://example.com/image.png';
					case 'text':
						return "What's in this image?";
					case 'simplify':
						return true;
					case 'options':
						return {
							maxTokens: 1024,
						};
					default:
						return undefined;
				}
			});
			executeFunctionsMock.getCredentials.mockResolvedValue({});
			apiRequestMock.mockResolvedValue({
				content: [
					{
						type: 'text',
						text: 'This image shows a beautiful sunset over a mountain landscape.',
					},
				],
				stop_reason: 'end_turn',
			});

			const result = await image.analyze.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						content: [
							{
								type: 'text',
								text: 'This image shows a beautiful sunset over a mountain landscape.',
							},
						],
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(apiRequestMock).toHaveBeenCalledWith('POST', '/v1/messages', {
				body: {
					model: 'claude-sonnet-4-20250514',
					max_tokens: 1024,
					messages: [
						{
							role: 'user',
							content: [
								{
									type: 'image',
									source: {
										type: 'url',
										url: 'https://example.com/image.png',
									},
								},
								{
									type: 'text',
									text: "What's in this image?",
								},
							],
						},
					],
				},
			});
		});

		it('should analyze image from binary data', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'inputType':
						return 'binary';
					case 'binaryPropertyName':
						return 'data';
					case 'text':
						return "What's in this image?";
					case 'simplify':
						return true;
					case 'options':
						return {
							maxTokens: 1024,
						};
					default:
						return undefined;
				}
			});
			executeFunctionsMock.getCredentials.mockResolvedValue({});
			const mockBinaryData: IBinaryData = {
				mimeType: 'image/png',
				fileName: 'test.png',
				fileSize: '2048',
				fileExtension: 'png',
				data: 'test',
			};
			executeFunctionsMock.helpers.assertBinaryData.mockReturnValue(mockBinaryData);
			executeFunctionsMock.helpers.getBinaryDataBuffer.mockResolvedValue(
				Buffer.from('test image data'),
			);
			apiRequestMock.mockResolvedValue({
				content: [
					{
						type: 'text',
						text: 'This image shows a beautiful sunset over a mountain landscape.',
					},
				],
				stop_reason: 'end_turn',
			});

			const result = await image.analyze.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						content: [
							{
								type: 'text',
								text: 'This image shows a beautiful sunset over a mountain landscape.',
							},
						],
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(apiRequestMock).toHaveBeenCalledWith('POST', '/v1/messages', {
				body: {
					model: 'claude-sonnet-4-20250514',
					max_tokens: 1024,
					messages: [
						{
							role: 'user',
							content: [
								{
									type: 'image',
									source: {
										type: 'base64',
										media_type: 'image/png',
										data: 'dGVzdCBpbWFnZSBkYXRh',
									},
								},
								{
									type: 'text',
									text: "What's in this image?",
								},
							],
						},
					],
				},
			});
		});

		it('should analyze image from Anthropic file URL', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'modelId':
						return 'claude-sonnet-4-20250514';
					case 'inputType':
						return 'url';
					case 'imageUrls':
						return 'https://api.anthropic.com/v1/files/file_123';
					case 'text':
						return "What's in this image?";
					case 'simplify':
						return true;
					case 'options':
						return {
							maxTokens: 1024,
						};
					default:
						return undefined;
				}
			});
			getBaseUrlMock.mockResolvedValue('https://api.anthropic.com');
			apiRequestMock.mockResolvedValue({
				content: [
					{
						type: 'text',
						text: 'This image shows a beautiful sunset over a mountain landscape.',
					},
				],
				stop_reason: 'end_turn',
			});

			const result = await image.analyze.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						content: [
							{
								type: 'text',
								text: 'This image shows a beautiful sunset over a mountain landscape.',
							},
						],
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(apiRequestMock).toHaveBeenCalledWith('POST', '/v1/messages', {
				body: {
					model: 'claude-sonnet-4-20250514',
					max_tokens: 1024,
					messages: [
						{
							role: 'user',
							content: [
								{
									type: 'image',
									source: {
										type: 'file',
										file_id: 'file_123',
									},
								},
								{
									type: 'text',
									text: "What's in this image?",
								},
							],
						},
					],
				},
			});
		});
	});

	describe('Prompt -> Generate', () => {
		it('should generate prompt from task description', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'task':
						return 'A chef for a meal prep planning service';
					case 'simplify':
						return true;
					default:
						return undefined;
				}
			});
			apiRequestMock.mockResolvedValue({
				messages: [
					{
						role: 'user',
						content: 'Plan a healthy weekly meal prep menu for busy professionals',
					},
				],
				system:
					'You are a professional chef specializing in meal prep services for busy professionals. Create balanced, nutritious, and convenient meal plans.',
			});

			const result = await prompt.generate.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						messages: [
							{
								role: 'user',
								content: 'Plan a healthy weekly meal prep menu for busy professionals',
							},
						],
						system:
							'You are a professional chef specializing in meal prep services for busy professionals. Create balanced, nutritious, and convenient meal plans.',
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(apiRequestMock).toHaveBeenCalledWith('POST', '/v1/experimental/generate_prompt', {
				body: {
					task: 'A chef for a meal prep planning service',
				},
				enableAnthropicBetas: {
					promptTools: true,
				},
			});
		});
	});

	describe('Prompt -> Improve', () => {
		it('should improve existing prompt with feedback', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'messages.values':
						return [
							{
								role: 'user',
								content: 'Plan meals for the week',
							},
						];
					case 'simplify':
						return true;
					case 'options':
						return {
							system: 'You are a chef',
							feedback: 'Make it more detailed and include cooking times',
						};
					default:
						return undefined;
				}
			});
			apiRequestMock.mockResolvedValue({
				messages: [
					{
						role: 'user',
						content:
							'Plan a detailed weekly meal prep menu with cooking times and nutritional information for busy professionals',
					},
				],
				system:
					'You are a professional chef and nutritionist specializing in meal prep services. Provide detailed cooking instructions, prep times, and nutritional breakdowns.',
			});

			const result = await prompt.improve.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						messages: [
							{
								role: 'user',
								content:
									'Plan a detailed weekly meal prep menu with cooking times and nutritional information for busy professionals',
							},
						],
						system:
							'You are a professional chef and nutritionist specializing in meal prep services. Provide detailed cooking instructions, prep times, and nutritional breakdowns.',
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(apiRequestMock).toHaveBeenCalledWith('POST', '/v1/experimental/improve_prompt', {
				body: {
					messages: [
						{
							role: 'user',
							content: 'Plan meals for the week',
						},
					],
					system: 'You are a chef',
					feedback: 'Make it more detailed and include cooking times',
				},
				enableAnthropicBetas: {
					promptTools: true,
				},
			});
		});
	});

	describe('Prompt -> Templatize', () => {
		it('should templatize prompt with variables', async () => {
			executeFunctionsMock.getNodeParameter.mockImplementation((parameter: string) => {
				switch (parameter) {
					case 'messages.values':
						return [
							{
								role: 'user',
								content: 'Translate hello to German',
							},
						];
					case 'simplify':
						return true;
					case 'options':
						return {
							system: 'You are a professional English to German translator',
						};
					default:
						return undefined;
				}
			});
			apiRequestMock.mockResolvedValue({
				messages: [
					{
						role: 'user',
						content: 'Translate {{WORD}} to {{TARGET_LANGUAGE}}',
					},
				],
				system: 'You are a professional {{SOURCE_LANGUAGE}} to {{TARGET_LANGUAGE}} translator',
				variable_values: {
					WORD: 'hello',
					TARGET_LANGUAGE: 'German',
					SOURCE_LANGUAGE: 'English',
				},
			});

			const result = await prompt.templatize.execute.call(executeFunctionsMock, 0);

			expect(result).toEqual([
				{
					json: {
						messages: [
							{
								role: 'user',
								content: 'Translate {{WORD}} to {{TARGET_LANGUAGE}}',
							},
						],
						system: 'You are a professional {{SOURCE_LANGUAGE}} to {{TARGET_LANGUAGE}} translator',
						variable_values: {
							WORD: 'hello',
							TARGET_LANGUAGE: 'German',
							SOURCE_LANGUAGE: 'English',
						},
					},
					pairedItem: { item: 0 },
				},
			]);
			expect(apiRequestMock).toHaveBeenCalledWith('POST', '/v1/experimental/templatize_prompt', {
				body: {
					messages: [
						{
							role: 'user',
							content: 'Translate hello to German',
						},
					],
					system: 'You are a professional English to German translator',
				},
				enableAnthropicBetas: {
					promptTools: true,
				},
			});
		});
	});
});
