/*---------------------------------------------------------
 * Copyright 2026 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

import assert from 'assert';
import os = require('os');
import * as path from 'path';
import sinon from 'sinon';
import * as vscode from 'vscode';
import * as config from '../../src/config';
import { GoExtensionContext } from '../../src/context';
import { handleErrors, ICheckResult } from '../../src/diagnostics/diagnostics';
import { lintCode } from '../../src/diagnostics/goLint';
import { MockWorkspaceConfiguration } from '../integration/mocks/configuration';
import { Env } from './goplsTestEnv.utils';

interface expectedDiagnostic {
	line: number;
	source: string;
	severity: vscode.DiagnosticSeverity;
}

function compareDiags(a: vscode.Diagnostic, b: vscode.Diagnostic): number {
	if (a.range.start.line !== b.range.start.line) {
		return a.range.start.line - b.range.start.line;
	}
	if (a.range.start.character !== b.range.start.character) {
		return a.range.start.character - b.range.start.character;
	}
	if (a.severity !== b.severity) {
		return a.severity - b.severity;
	}
	return (a.source ?? '').localeCompare(b.source ?? '');
}

suite('Diagnostic consolidation - unit', () => {
	let goCtx: GoExtensionContext;

	const fileURI = vscode.Uri.file(path.join(os.tmpdir(), 'diagnostic_priority_test.go')); // fake file
	const filePath = fileURI.fsPath;

	interface TestDiagnosticTestCase {
		name: string;
		diags: {
			gopls?: ICheckResult[];
			build?: ICheckResult[];
			vet?: ICheckResult[];
			lint?: ICheckResult[];
		};
		want: expectedDiagnostic[];
	}

	const testCases: TestDiagnosticTestCase[] = [
		{
			name: 'Symmetric priority masking (Gopls > Build > Vet > Lint)',
			diags: {
				gopls: [{ file: filePath, line: 10, msg: 'unmasked - highest priority', severity: 'warning' }],
				build: [
					{ file: filePath, line: 10, msg: 'masked by gopls', severity: 'warning' },
					{ file: filePath, line: 20, msg: 'unmasked - no higher priority', severity: 'warning' }
				],
				vet: [
					{ file: filePath, line: 10, msg: 'masked by gopls', severity: 'warning' },
					{ file: filePath, line: 20, msg: 'masked by build', severity: 'warning' },
					{ file: filePath, line: 30, msg: 'unmasked - no higher priority', severity: 'warning' }
				],
				lint: [
					{ file: filePath, line: 10, msg: 'masked by gopls', severity: 'warning' },
					{ file: filePath, line: 20, msg: 'masked by build', severity: 'warning' },
					{ file: filePath, line: 30, msg: 'masked by vet', severity: 'warning' },
					{ file: filePath, line: 40, msg: 'unmasked - no higher priority', severity: 'warning' }
				]
			},
			want: [
				{ line: 10, source: 'gopls-test', severity: vscode.DiagnosticSeverity.Warning },
				{ line: 20, source: 'build-test', severity: vscode.DiagnosticSeverity.Warning },
				{ line: 30, source: 'vet-test', severity: vscode.DiagnosticSeverity.Warning },
				{ line: 40, source: 'lint-test', severity: vscode.DiagnosticSeverity.Warning }
			]
		},
		{
			name: 'Diagnostics with columns and severity',
			diags: {
				gopls: [{ file: filePath, line: 10, col: 5, msg: 'unmasked - highest priority', severity: 'error' }],
				build: [
					{ file: filePath, line: 10, col: 5, msg: 'masked by gopls', severity: 'error' },
					{ file: filePath, line: 20, col: 12, msg: 'unmasked - no higher priority', severity: 'error' }
				],
				vet: [
					{ file: filePath, line: 20, col: 12, msg: 'masked by build', severity: 'warning' },
					{ file: filePath, line: 30, col: 8, msg: 'unmasked - no higher priority', severity: 'warning' }
				],
				lint: [
					{ file: filePath, line: 30, col: 8, msg: 'masked by vet', severity: 'warning' },
					{ file: filePath, line: 40, col: 15, msg: 'unmasked - no higher priority', severity: 'warning' }
				]
			},
			want: [
				{ line: 10, source: 'gopls-test', severity: vscode.DiagnosticSeverity.Error },
				{ line: 20, source: 'build-test', severity: vscode.DiagnosticSeverity.Error },
				{ line: 30, source: 'vet-test', severity: vscode.DiagnosticSeverity.Warning },
				{ line: 40, source: 'lint-test', severity: vscode.DiagnosticSeverity.Warning }
			]
		},
		{
			name: 'Same line, different columns, same severity',
			diags: {
				gopls: [{ file: filePath, line: 10, col: 5, msg: 'unmasked - highest priority', severity: 'error' }],
				build: [
					{ file: filePath, line: 10, col: 5, msg: 'masked by gopls', severity: 'error' },
					{ file: filePath, line: 10, col: 15, msg: 'unmasked - no higher priority', severity: 'error' }
				],
				vet: [{ file: filePath, line: 10, col: 25, msg: 'unmasked - no higher priority', severity: 'error' }],
				lint: [{ file: filePath, line: 10, col: 35, msg: 'unmasked - no higher priority', severity: 'error' }]
			},
			want: [
				{ line: 10, source: 'gopls-test', severity: vscode.DiagnosticSeverity.Error },
				{ line: 10, source: 'build-test', severity: vscode.DiagnosticSeverity.Error },
				{ line: 10, source: 'vet-test', severity: vscode.DiagnosticSeverity.Error },
				{ line: 10, source: 'lint-test', severity: vscode.DiagnosticSeverity.Error }
			]
		},
		{
			name: 'Same line and column, lower priority has higher severity',
			diags: {
				gopls: [{ file: filePath, line: 10, col: 5, msg: 'unmasked - highest priority', severity: 'warning' }],
				lint: [
					{ file: filePath, line: 10, col: 5, msg: 'masked by gopls', severity: 'warning' },
					{
						file: filePath,
						line: 10,
						col: 5,
						msg: 'unmasked - higher severity than gopls warning',
						severity: 'error'
					}
				]
			},
			want: [
				{ line: 10, source: 'lint-test', severity: vscode.DiagnosticSeverity.Error },
				{ line: 10, source: 'gopls-test', severity: vscode.DiagnosticSeverity.Warning }
			]
		}
	];

	setup(() => {
		goCtx = {
			languageClient: { diagnostics: vscode.languages.createDiagnosticCollection('gopls-test') } as any,
			buildDiagnosticCollection: vscode.languages.createDiagnosticCollection('build-test'),
			vetDiagnosticCollection: vscode.languages.createDiagnosticCollection('vet-test'),
			lintDiagnosticCollection: vscode.languages.createDiagnosticCollection('lint-test')
		};
	});

	teardown(() => {
		goCtx.languageClient?.diagnostics?.dispose();
		goCtx.buildDiagnosticCollection?.dispose();
		goCtx.vetDiagnosticCollection?.dispose();
		goCtx.lintDiagnosticCollection?.dispose();
	});

	for (const tc of testCases) {
		for (let round = 1; round <= 5; round++) {
			test(`${tc.name} (round ${round})`, async () => {
				const collections = [
					{ key: 'gopls' as const, collection: goCtx.languageClient!.diagnostics! },
					{ key: 'build' as const, collection: goCtx.buildDiagnosticCollection! },
					{ key: 'vet' as const, collection: goCtx.vetDiagnosticCollection! },
					{ key: 'lint' as const, collection: goCtx.lintDiagnosticCollection! }
				];

				// Simulate 4 concurrent diagnostic providers reporting diags
				// independently with random delays to verify eventual consistency.
				const tasks = collections.map(({ key, collection }) => {
					const errors = tc.diags[key] || [];
					return new Promise<void>((resolve) => {
						const delay = Math.floor(Math.random() * 15);
						setTimeout(() => {
							handleErrors(goCtx, undefined, errors, collection);
							resolve();
						}, delay);
					});
				});

				// Wait for all concurrent diagnostic providers to finish reporting.
				await Promise.all(tasks);

				// Read diagnostics directly from the "PROBLEMS" tab.
				const problems = vscode.languages.getDiagnostics(fileURI);
				const sorted = [...problems].sort(compareDiags);

				assert.strictEqual(
					sorted.length,
					tc.want.length,
					`[${tc.name}] Expected ${tc.want.length} diagnostics, got ${sorted.length}: ${JSON.stringify(sorted.map((p) => ({ line: p.range.start.line + 1, source: p.source, msg: p.message })))}`
				);

				for (let i = 0; i < tc.want.length; i++) {
					const want = tc.want[i];
					const got = sorted[i];
					assert.strictEqual(got.range.start.line, want.line - 1, `[${tc.name}] Line mismatch at index ${i}`);
					assert.strictEqual(got.source, want.source, `[${tc.name}] Source mismatch at index ${i}`);
					assert.strictEqual(got.severity, want.severity, `[${tc.name}] Severity mismatch at index ${i}`);
				}
			});
		}
	}
});

// Regression tests for golang/vscode-go#3511.
suite('Diagnostic consolidation - regression (#3511)', function () {
	this.timeout(30000);
	const projectDir = path.join(__dirname, '..', '..', '..');
	const testdataDir = path.join(projectDir, 'test', 'testdata', 'diagnosticsTest');
	let env: Env;

	async function pollDiagnostics(uri: vscode.Uri, predicate: (diags: vscode.Diagnostic[]) => boolean): Promise<void> {
		const start = Date.now();
		// Polling deadline of 10s. Analyzing a module with only a few files
		// should finish within 10s for both gopls and external linters.
		while (Date.now() - start < 10000) {
			const problems = vscode.languages.getDiagnostics(uri);
			if (predicate(problems)) {
				return;
			}
			await new Promise((resolve) => setTimeout(resolve, 50));
		}
		assert.fail(
			`timed out waiting for expected diags on ${path.basename(uri.fsPath)}, got: ${JSON.stringify(
				vscode.languages
					.getDiagnostics(uri)
					.map((p) => ({ line: p.range.start.line + 1, source: p.source, msg: p.message }))
			)}`
		);
	}

	suiteSetup(async () => {
		env = new Env();
		const goplsConfig = new MockWorkspaceConfiguration(
			config.getGoplsConfig(),
			new Map<string, any>([
				['ui.diagnostic.staticcheck', true],
				['ui.diagnostic.analyses', { ST1017: true }]
			])
		);
		sinon.stub(config, 'getGoplsConfig').returns(goplsConfig);

		const goConfig = new MockWorkspaceConfiguration(
			config.getGoConfig(),
			new Map<string, any>([
				['lintTool', 'golangci-lint-v2'],
				['lintOnSave', 'package']
			])
		);
		sinon.stub(config, 'getGoConfig').returns(goConfig);

		env.goCtx.lintDiagnosticCollection = vscode.languages.createDiagnosticCollection('go-lint');

		// Start gopls with workspace
		await env.startGopls(path.join(testdataDir, 'masked.go'), undefined, testdataDir);

		// Open both documents to trigger gopls diagnostics
		const { doc: coexistDoc } = await env.openDoc(path.join(testdataDir, 'coexist.go'));
		const { doc: maskedDoc } = await env.openDoc(path.join(testdataDir, 'masked.go'));
		await vscode.window.showTextDocument(coexistDoc);

		// Run linter once for the package
		lintCode('package')(undefined as any, env.goCtx)();

		// Wait until diagnostics from both gopls and linter are ready
		await pollDiagnostics(coexistDoc.uri, (diags) => diags.length >= 2);
		await pollDiagnostics(maskedDoc.uri, (diags) => diags.length >= 1);
	});

	suiteTeardown(async () => {
		sinon.restore();
		env.goCtx.lintDiagnosticCollection?.dispose();
		await env.teardown();
		env.flushTrace(false);
	});

	interface DiagnosticTestCase {
		name: string;
		fileName: string;
		want: expectedDiagnostic[];
	}

	const testCases: DiagnosticTestCase[] = [
		{
			name: 'coexist',
			fileName: 'coexist.go',
			// golangci-lint-v2 report a more severe diags so that persist.
			want: [
				{ line: 8, source: 'any', severity: vscode.DiagnosticSeverity.Hint },
				{ line: 8, source: 'go-lint', severity: vscode.DiagnosticSeverity.Warning }
			]
		},
		{
			name: 'masked',
			fileName: 'masked.go',
			// golangci-lint-v2 will report the same diags but prefer gopls'.
			want: [{ line: 4, source: 'ST1017', severity: vscode.DiagnosticSeverity.Warning }]
		}
	];

	for (const tc of testCases) {
		test(tc.name, () => {
			const uri = vscode.Uri.file(path.join(testdataDir, tc.fileName));
			const problems = vscode.languages.getDiagnostics(uri);
			const sorted = [...problems].sort(compareDiags);

			assert.strictEqual(
				sorted.length,
				tc.want.length,
				`[${tc.name}] Expected ${tc.want.length} diagnostics, got ${sorted.length}: ${JSON.stringify(sorted.map((p) => ({ line: p.range.start.line + 1, source: p.source, msg: p.message })))}`
			);

			for (let i = 0; i < tc.want.length; i++) {
				const want = tc.want[i];
				const got = sorted[i];
				assert.strictEqual(got.range.start.line, want.line - 1, `[${tc.name}] Line mismatch at index ${i}`);
				assert.strictEqual(got.source, want.source, `[${tc.name}] Source mismatch at index ${i}`);
				assert.strictEqual(got.severity, want.severity, `[${tc.name}] Severity mismatch at index ${i}`);
			}
		});
	}
});
