import { expect, test } from '../../../../fixtures/base';
import type { n8nPage } from '../../../../pages/n8nPage';
import {
	buildRepoUrl,
	generateUniqueRepoName,
	initSourceControl,
} from '../../../../utils/source-control-helper';

test.use({ capability: 'source-control' });

async function saveSettings(n8n: n8nPage) {
	await n8n.settingsEnvironment.getSaveButton().click();
	await n8n.page.waitForResponse(
		(response) =>
			response.url().includes('/rest/source-control/preferences') &&
			response.request().method() === 'PATCH',
	);
}

// Skipped: These tests are flaky. Re-enable when PAY-4365 is resolved.
// https://linear.app/n8n/issue/PAY-4365/bug-source-control-operations-fail-in-multi-main-deployment
test.describe(
	'Source Control Settings @capability:source-control',
	{
		annotation: [{ type: 'owner', description: 'Lifecycle & Governance' }],
	},
	() => {
		test.fixme();

		let repoUrl: string;
		let repoName: string;

		test.beforeEach(async ({ n8n, services }) => {
			await n8n.api.enableFeature('sourceControl');
			const gitea = services.gitea;
			await initSourceControl({ n8n, gitea });

			// Create unique repo with branches via API (not UI)
			repoName = generateUniqueRepoName();
			await gitea.createRepo(repoName);

			repoUrl = buildRepoUrl(repoName);
		});

		test('should connect to Git repository using SSH', async ({ n8n }) => {
			// Test UI connection flow with unique repo
			await n8n.navigate.toEnvironments();

			await n8n.settingsEnvironment.fillRepoUrl(repoUrl);
			await expect(n8n.settingsEnvironment.getConnectButton()).toBeEnabled();
			await n8n.settingsEnvironment.getConnectButton().click();

			await expect(n8n.settingsEnvironment.getDisconnectButton()).toBeVisible();
			await expect(n8n.settingsEnvironment.getBranchSelect()).toBeVisible();

			await n8n.settingsEnvironment.getBranchSelect().click();
			await expect(n8n.page.getByRole('option', { name: 'main' })).toBeVisible();

			// Verify source control connected indicator is visible
			await n8n.navigate.toHome();
			await expect(n8n.sideBar.getSourceControlConnectedIndicator()).toBeVisible();
		});

		test('should switch between branches', async ({ n8n, services }) => {
			const gitea = services.gitea;
			await gitea.createBranch(repoName, 'development');
			await gitea.createBranch(repoName, 'staging');
			await gitea.createBranch(repoName, 'production');

			await n8n.api.sourceControl.connect({ repositoryUrl: repoUrl });

			await n8n.navigate.toEnvironments();

			// Switch to 'development' branch
			await n8n.settingsEnvironment.getBranchSelect().click();
			await expect(n8n.page.getByRole('option', { name: 'main' })).toBeVisible();
			await expect(n8n.page.getByRole('option', { name: 'development' })).toBeVisible();
			await expect(n8n.page.getByRole('option', { name: 'staging' })).toBeVisible();
			await expect(n8n.page.getByRole('option', { name: 'production' })).toBeVisible();
			await n8n.page.getByRole('option', { name: 'development' }).click();
			await saveSettings(n8n);

			// Verify branch switched by checking preferences
			let preferencesResponse = await n8n.page.request.get('/rest/source-control/preferences');
			let preferences = await preferencesResponse.json();
			expect(preferences.data.branchName).toBe('development');

			// Switch back to 'main'
			await n8n.settingsEnvironment.selectBranch('main');
			await saveSettings(n8n);

			// Verify switched back
			preferencesResponse = await n8n.page.request.get('/rest/source-control/preferences');
			preferences = await preferencesResponse.json();
			expect(preferences.data.branchName).toBe('main');
		});

		test('should enable read-only mode and restrict operations', async ({ n8n }) => {
			await n8n.api.sourceControl.connect({ repositoryUrl: repoUrl });

			await n8n.navigate.toEnvironments();

			await n8n.settingsEnvironment.enableReadOnlyMode();
			await saveSettings(n8n);

			// Verify push button is disabled in read-only mode
			await n8n.navigate.toHome();
			await expect(n8n.sideBar.getSourceControlPushButton()).toBeDisabled();
			await expect(n8n.sideBar.getSourceControlPullButton()).toBeEnabled();

			await n8n.navigate.toEnvironments();
			await n8n.settingsEnvironment.disableReadOnlyMode();
			await saveSettings(n8n);

			// Verify push button is enabled again
			await n8n.navigate.toHome();
			await expect(n8n.sideBar.getSourceControlPushButton()).toBeEnabled();
			await expect(n8n.sideBar.getSourceControlPullButton()).toBeEnabled();
		});

		test('should disconnect and reconnect with existing keys', async ({ n8n }) => {
			await n8n.api.sourceControl.connect({ repositoryUrl: repoUrl });

			await n8n.navigate.toEnvironments();
			await n8n.settingsEnvironment.disconnect();

			// check that source control is disconnected
			await n8n.navigate.toHome();
			await expect(n8n.sideBar.getSourceControlConnectedIndicator()).toBeHidden();

			// Reconnect
			await n8n.navigate.toEnvironments();
			await n8n.settingsEnvironment.fillRepoUrl(repoUrl);
			await expect(n8n.settingsEnvironment.getConnectButton()).toBeEnabled();
			await n8n.settingsEnvironment.getConnectButton().click();

			await expect(n8n.settingsEnvironment.getDisconnectButton()).toBeVisible();
			await expect(n8n.settingsEnvironment.getBranchSelect()).toBeVisible();

			// check that source control is connected
			await n8n.navigate.toHome();
			await expect(n8n.sideBar.getSourceControlConnectedIndicator()).toBeVisible();
		});
	},
);
