import { test, expect } from '../../../fixtures/base';
import type { n8nPage } from '../../../pages/n8nPage';

test.describe(
	'Security Notifications',
	{
		annotation: [{ type: 'owner', description: 'Adore' }],
	},
	() => {
		async function setupVersionsApiMock(
			n8n: n8nPage,
			options: {
				hasSecurityIssue?: boolean;
				hasSecurityFix?: boolean;
				securityIssueFixVersion?: string;
			} = {},
		) {
			const {
				hasSecurityIssue = false,
				hasSecurityFix = false,
				securityIssueFixVersion = '',
			} = options;

			await n8n.page.route('**/api/versions/**', async (route) => {
				// Extract current version from URL path
				const url = route.request().url();
				const currentVersion = url.split('/').pop() ?? '1.106.1';

				// Parse version to create next version
				const versionParts = currentVersion.split('.');
				const nextPatchVersion = `${versionParts[0]}.${versionParts[1]}.${parseInt(versionParts[2]) + 1}`;

				const mockVersions = [
					{
						name: currentVersion,
						nodes: [],
						createdAt: '2025-06-24T00:00:00Z',
						description: hasSecurityIssue
							? 'Current version with security issue'
							: 'Current version',
						documentationUrl: 'https://docs.n8n.io',
						hasBreakingChange: false,
						hasSecurityFix: false,
						hasSecurityIssue,
						securityIssueFixVersion:
							securityIssueFixVersion === 'useNextPatch'
								? nextPatchVersion
								: securityIssueFixVersion,
					},
					{
						name: nextPatchVersion,
						nodes: [],
						createdAt: '2025-06-25T00:00:00Z',
						description: hasSecurityFix ? 'Fixed version' : 'Next version',
						documentationUrl: 'https://docs.n8n.io',
						hasBreakingChange: false,
						hasSecurityFix,
						hasSecurityIssue: false,
						securityIssueFixVersion: '',
					},
				];
				await route.fulfill({ json: mockVersions });
			});
		}

		async function setupApiFailure(n8n: n8nPage) {
			await n8n.page.route('**/api/versions/**', async (route) => {
				await route.fulfill({
					status: 500,
					contentType: 'application/json',
					body: JSON.stringify({ error: 'API Error' }),
				});
			});
		}

		test.describe('Notifications disabled', () => {
			test.beforeEach(async ({ setupRequirements }) => {
				await setupRequirements({
					config: {
						settings: {
							versionNotifications: {
								enabled: false,
								endpoint: 'https://test.api.n8n.io/api/versions/',
								whatsNewEnabled: false,
								whatsNewEndpoint: 'https://test.api.n8n.io/api/whats-new',
								infoUrl: 'https://test.docs.n8n.io/hosting/installation/updating/',
							},
						},
					},
				});
			});

			test('should not check for versions if feature is disabled', async ({ n8n }) => {
				// Track whether any API requests are made to versions endpoint
				let versionsApiCalled = false;

				await n8n.page.route('**/api/versions/**', () => {
					versionsApiCalled = true;
				});

				await n8n.goHome();

				// Wait a moment for any potential API calls or notifications
				// eslint-disable-next-line playwright/no-networkidle
				await n8n.page.waitForLoadState('networkidle');

				// Verify no API request was made to versions endpoint when notifications are disabled
				expect(versionsApiCalled).toBe(false);
			});
		});

		test.describe('Notifications enabled', () => {
			test.beforeEach(async ({ setupRequirements }) => {
				await setupRequirements({
					config: {
						settings: {
							versionNotifications: {
								enabled: true,
								endpoint: 'https://test.api.n8n.io/api/versions/',
								whatsNewEnabled: true,
								whatsNewEndpoint: 'https://test.api.n8n.io/api/whats-new',
								infoUrl: 'https://test.docs.n8n.io/hosting/installation/updating/',
							},
						},
					},
				});
			});

			test('should display security notification with correct messaging and styling', async ({
				n8n,
			}) => {
				await setupVersionsApiMock(n8n, { hasSecurityIssue: true, hasSecurityFix: true });

				// Reload to trigger version check
				await n8n.page.reload();
				await n8n.goHome();

				// Verify security notification appears with default message
				const notification = n8n.notifications.getNotificationByTitle('Critical update available');
				await expect(notification).toBeVisible();
				await expect(notification).toContainText('Please update to latest version.');
				await expect(notification).toContainText('More info');

				// Verify warning styling
				await expect(n8n.notifications.getWarningNotifications()).toBeVisible();

				// Close the notification
				await n8n.notifications.closeNotificationByText('Critical update available');

				// Now test with specific fix version
				await setupVersionsApiMock(n8n, {
					hasSecurityIssue: true,
					hasSecurityFix: true,
					securityIssueFixVersion: 'useNextPatch',
				});

				// Reload to trigger new version check with fix version
				await n8n.goHome();

				// Verify notification shows specific fix version (dynamically generated)
				const notificationWithFixVersion = n8n.notifications.getNotificationByTitle(
					'Critical update available',
				);
				await expect(notificationWithFixVersion).toBeVisible();
				await expect(notificationWithFixVersion).toContainText('Please update to version');
				await expect(notificationWithFixVersion).toContainText('or higher.');
			});

			test('should open versions modal when clicking security notification', async ({ n8n }) => {
				await setupVersionsApiMock(n8n, {
					hasSecurityIssue: true,
					hasSecurityFix: true,
					securityIssueFixVersion: 'useNextPatch',
				});

				await n8n.goHome();

				// Wait for and click the security notification
				const notification = n8n.notifications.getNotificationByTitle('Critical update available');
				await expect(notification).toBeVisible();
				await notification.click();

				// Verify versions modal opens
				const versionsModal = n8n.versions.container;
				await expect(versionsModal).toBeVisible();

				// Verify security update badge exists for the new version
				const versionCard = n8n.versions.getVersionCard().first();
				const securityBadge = versionCard.locator('.el-tag--danger').getByText('Security update');
				await expect(securityBadge).toBeVisible();
			});

			test('should not display security notification when theres no security issue', async ({
				n8n,
			}) => {
				await setupVersionsApiMock(n8n, { hasSecurityIssue: false });

				await n8n.goHome();

				// Verify no security notification appears when no security issue
				const notification = n8n.notifications.getNotificationByTitle('Critical update available');
				await expect(notification).toBeHidden();
			});

			test('should handle API failure gracefully', async ({ n8n }) => {
				// Enable notifications but mock API failure
				await setupApiFailure(n8n);

				await n8n.goHome();
				const { projectId } = await n8n.projectComposer.createProject();
				await n8n.page.goto(`projects/${projectId}/workflows`);

				// Verify no security notification appears on API failure
				const notification = n8n.notifications.getNotificationByTitle('Critical update available');
				await expect(notification).toBeHidden();

				// Verify the app still functions normally
				await expect(n8n.workflows.getProjectName()).toBeVisible();
			});
		});
	},
);
