import {
	simpleAssistantResponse,
	aiEnabledWithCodeSnippetRequirements,
	aiEnabledWithHttpWorkflowRequirements,
} from '../../../config/ai-assistant-fixtures';
import { HTTP_REQUEST_NODE_NAME } from '../../../config/constants';
import { test, expect } from '../../../fixtures/base';

type ChatRequestBody = {
	payload?: {
		type?: string;
		text?: string;
		question?: string;
		context?: Record<string, unknown>;
	};
};

test.describe('AI Assistant::enabled', () => {
	test.describe('Support Chat', () => {
		test('assistant returns code snippet', async ({ n8n, setupRequirements }) => {
			await setupRequirements(aiEnabledWithCodeSnippetRequirements);
			await n8n.page.goto('/workflow/new');

			await expect(n8n.aiAssistant.getAskAssistantCanvasActionButton()).toBeVisible();
			await n8n.aiAssistant.getAskAssistantCanvasActionButton().click();

			await expect(n8n.aiAssistant.getAskAssistantChat()).toBeVisible();

			await n8n.aiAssistant.sendMessage('Show me an expression');

			await expect(n8n.aiAssistant.getChatMessagesAll()).toHaveCount(3);
			await expect(n8n.aiAssistant.getChatMessagesUser().first()).toContainText(
				'Show me an expression',
			);
			await expect(n8n.aiAssistant.getChatMessagesAssistant().first()).toContainText(
				'To use expressions in n8n, follow these steps:',
			);
			await expect(n8n.aiAssistant.getChatMessagesAssistant().first()).toContainText('New York');
			await expect(n8n.aiAssistant.getCodeSnippet()).toHaveText('{{$json.body.city}}');
		});

		test('should send current context to support chat', async ({ n8n, setupRequirements }) => {
			await setupRequirements(aiEnabledWithHttpWorkflowRequirements);

			const chatRequests: ChatRequestBody[] = [];
			await n8n.page.route('**/rest/ai/chat', async (route) => {
				const body = route.request().postDataJSON() as ChatRequestBody;
				chatRequests.push(body);
				await route.fulfill({
					status: 200,
					contentType: 'application/json',
					body: JSON.stringify(simpleAssistantResponse),
				});
			});

			await n8n.aiAssistant.getAskAssistantCanvasActionButton().click();
			await n8n.aiAssistant.sendMessage('What is wrong with this workflow?');

			const supportRequest = chatRequests.find(
				(request) => request.payload?.question === 'What is wrong with this workflow?',
			);
			expect(supportRequest).toBeDefined();
			const supportContext = supportRequest?.payload?.context;
			expect(supportContext).toBeDefined();
			expect(supportContext?.currentView).toBeDefined();
			expect(supportContext?.currentWorkflow).toBeDefined();
		});

		test('should not send workflow context if nothing changed', async ({
			n8n,
			setupRequirements,
		}) => {
			await setupRequirements(aiEnabledWithHttpWorkflowRequirements);

			const chatRequests: ChatRequestBody[] = [];
			await n8n.page.route('**/rest/ai/chat', async (route) => {
				const body = route.request().postDataJSON() as ChatRequestBody;
				chatRequests.push(body);
				await route.fulfill({
					status: 200,
					contentType: 'application/json',
					body: JSON.stringify(simpleAssistantResponse),
				});
			});

			await n8n.aiAssistant.getAskAssistantCanvasActionButton().click();

			await n8n.aiAssistant.sendMessage('What is wrong with this workflow?', 'enter-key');
			// Wait for message to be processed
			await expect(n8n.aiAssistant.getChatMessagesAssistant()).toHaveCount(1);

			await n8n.aiAssistant.sendMessage('And now?', 'enter-key');
			await expect(n8n.aiAssistant.getChatMessagesAssistant()).toHaveCount(2);
			const secondRequest = chatRequests.find((request) => request.payload?.text === 'And now?');
			const secondContext = secondRequest?.payload?.context;
			expect(secondContext?.currentWorkflow).toBeUndefined();

			await n8n.canvas.openNode(HTTP_REQUEST_NODE_NAME);
			await n8n.ndv.setParameterInputValue('url', 'https://example.com');
			await n8n.ndv.close();
			await n8n.canvas.clickExecuteWorkflowButton();

			await n8n.aiAssistant.sendMessage('What about now?', 'enter-key');
			await expect(n8n.aiAssistant.getChatMessagesAssistant()).toHaveCount(3);

			const thirdRequest = chatRequests.find(
				(request) => request.payload?.text === 'What about now?',
			);
			const thirdContext = thirdRequest?.payload?.context;
			expect(thirdContext?.currentWorkflow).toBeTruthy();
			expect(thirdContext?.executionData).toBeTruthy();
		});
	});
});
