import { mockInstance } from '@n8n/backend-test-utils';
import { User } from '@n8n/db';

import { createWorkflow } from './mock.utils';
import { getWorkflowDetails, createWorkflowDetailsTool } from '../tools/get-workflow-details.tool';

import { CredentialsService } from '@/credentials/credentials.service';
import { ProjectService } from '@/services/project.service.ee';
import { RoleService } from '@/services/role.service';
import { Telemetry } from '@/telemetry';
import { WorkflowFinderService } from '@/workflows/workflow-finder.service';

import { v4 as uuid } from 'uuid';

jest.mock('../tools/webhook-utils', () => ({
	getTriggerDetails: jest.fn().mockResolvedValue('MOCK_TRIGGER_DETAILS'),
}));

describe('get-workflow-details MCP tool', () => {
	const user = Object.assign(new User(), { id: 'user-1' });
	const baseWebhookUrl = 'https://example.test';

	describe('smoke tests', () => {
		test('it creates tool correctly', () => {
			const workflowFinderService = mockInstance(WorkflowFinderService, {
				findWorkflowForUser: jest.fn(),
			});
			const credentialsService = mockInstance(CredentialsService, {});
			const telemetry = mockInstance(Telemetry, {
				track: jest.fn(),
			});
			const roleService = mockInstance(RoleService, {
				addScopes: jest.fn((wf) => ({ ...wf, scopes: [] })) as unknown as RoleService['addScopes'],
			});
			const projectService = mockInstance(ProjectService, {
				getProjectRelationsForUser: jest.fn().mockResolvedValue([]),
			});
			const endpoints = { webhook: 'webhook', webhookTest: 'webhook-test' };

			const tool = createWorkflowDetailsTool(
				user,
				baseWebhookUrl,
				workflowFinderService,
				credentialsService,
				endpoints,
				telemetry,
				roleService,
				projectService,
			);

			expect(tool.name).toBe('get_workflow_details');
			expect(tool.config).toBeDefined();
			expect(typeof tool.config.description).toBe('string');
			expect(tool.config.inputSchema).toBeDefined();
			expect(typeof tool.handler).toBe('function');
		});
	});

	describe('handler tests', () => {
		const roleService = mockInstance(RoleService, {
			addScopes: jest.fn((wf) => ({
				...wf,
				scopes: ['workflow:read', 'workflow:execute'],
			})) as unknown as RoleService['addScopes'],
		});
		const projectService = mockInstance(ProjectService, {
			getProjectRelationsForUser: jest.fn().mockResolvedValue([]),
		});

		test('returns sanitized workflow and trigger info (active)', async () => {
			const workflow = createWorkflow({ activeVersionId: uuid() });
			const workflowFinderService = mockInstance(WorkflowFinderService, {
				findWorkflowForUser: jest.fn().mockResolvedValue(workflow),
			});
			const credentialsService = mockInstance(CredentialsService, {});
			const endpoints = { webhook: 'webhook', webhookTest: 'webhook-test' };

			const payload = await getWorkflowDetails(
				user,
				baseWebhookUrl,
				workflowFinderService,
				credentialsService,
				endpoints,
				roleService,
				projectService,
				{ workflowId: 'wf-1' },
			);

			expect('pinData' in payload.workflow).toBe(false);
			expect(payload.workflow.nodes.every((n) => !('credentials' in n))).toBe(true);
			expect(payload.triggerInfo).toContain('MOCK_TRIGGER_DETAILS');
			expect(payload.workflow.versionId).toBe(workflow.versionId);
			expect(payload.workflow.activeVersionId).toBe(workflow.activeVersionId);
			expect(payload.workflow.activeVersion).not.toBeNull();
			expect(payload.workflow.activeVersion?.nodes.every((n) => !('credentials' in n))).toBe(true);
			expect(payload.workflow.scopes).toEqual(['workflow:read', 'workflow:execute']);
			expect(payload.workflow.canExecute).toBe(true);
		});

		test('propagates errors from workflow validation', async () => {
			const credentialsService = mockInstance(CredentialsService, {});
			const endpoints = { webhook: 'webhook', webhookTest: 'webhook-test' };

			const wfFinder = mockInstance(WorkflowFinderService, {
				findWorkflowForUser: jest.fn().mockResolvedValue(null),
			});

			await expect(
				getWorkflowDetails(
					user,
					baseWebhookUrl,
					wfFinder,
					credentialsService,
					endpoints,
					roleService,
					projectService,
					{ workflowId: 'any-id' },
				),
			).rejects.toThrow();
		});

		test('returns null activeVersion for unpublished workflows', async () => {
			const unpublished = createWorkflow({ activeVersionId: null });
			const workflowFinderService = mockInstance(WorkflowFinderService, {
				findWorkflowForUser: jest.fn().mockResolvedValue(unpublished),
			});
			const credentialsService = mockInstance(CredentialsService, {});
			const endpoints = { webhook: 'webhook', webhookTest: 'webhook-test' };

			const payload = await getWorkflowDetails(
				user,
				baseWebhookUrl,
				workflowFinderService,
				credentialsService,
				endpoints,
				roleService,
				projectService,
				{ workflowId: 'wf-1' },
			);

			expect(payload.workflow.activeVersion).toBeNull();
			expect(payload.workflow.activeVersionId).toBeNull();
		});
	});
});
