/* eslint-disable no-async-promise-executor */
/* eslint-disable @typescript-eslint/no-explicit-any */
/*---------------------------------------------------------
 * Copyright (C) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------*/

import AdmZip = require('adm-zip');
import assert from 'assert';
import * as config from '../../src/config';
import {
	IToolsManager,
	defaultToolsManager,
	inspectGoToolVersion,
	installTools,
	maybeInstallImportantTools
} from '../../src/goInstallTools';
import { Tool, getRequiredTools, getTool, getToolAtVersion } from '../../src/goTools';
import { getBinPath, getGoVersion, GoVersion, rmdirRecursive } from '../../src/util';
import { correctBinname } from '../../src/utils/pathUtils';
import cp = require('child_process');
import fs = require('fs');
import os = require('os');
import path = require('path');
import sinon = require('sinon');
import url = require('url');
import util = require('util');
import vscode = require('vscode');
import { allToolsInformation } from '../../src/goToolsInformation';
import * as goInstallTools from '../../src/goInstallTools';
import * as utilModule from '../../src/util';
import { getGoConfig } from '../../src/config';
import { MockWorkspaceConfiguration } from './mocks/configuration';

interface installationTestCase {
	name: string;
	versions?: string[];
	wantVersion?: string;
}

suite('Installation Tests', function () {
	// Disable timeout when we are running slow tests.
	let timeout = 60000;
	if (shouldRunSlowTests()) {
		timeout = 0;
	}
	this.timeout(timeout);

	let tmpToolsGopath: string;
	let tmpToolsGopath2: string;
	let sandbox: sinon.SinonSandbox;
	let toolsGopath: string;

	setup(() => {
		// Create a temporary directory in which to install tools.
		tmpToolsGopath = fs.mkdtempSync(path.join(os.tmpdir(), 'install-test'));

		// a temporary directory to be used as the second GOPATH element.
		tmpToolsGopath2 = fs.mkdtempSync(path.join(os.tmpdir(), 'install-test2'));

		toolsGopath = tmpToolsGopath + path.delimiter + tmpToolsGopath2;

		sandbox = sinon.createSandbox();
	});

	teardown(async () => {
		sandbox.restore();

		// Clean up the temporary GOPATH. To delete the module cache, run `go clean -modcache`.
		const goRuntimePath = getBinPath('go');
		for (const p of [tmpToolsGopath, tmpToolsGopath2]) {
			const envForTest = Object.assign({}, process.env);
			envForTest['GOPATH'] = p;
			envForTest['GOMODCACHE'] = path.join(p, 'pkg', 'mod');
			const execFile = util.promisify(cp.execFile);
			try {
				await execFile(goRuntimePath, ['clean', '-x', '-modcache'], {
					env: envForTest
				});
				rmdirRecursive(p);
			} catch (e) {
				console.log(`failed to clean module cache directory: ${e}`);
			}
		}
	});

	// runTest actually executes the logic of the test.
	// If withLocalProxy is true, the test does not require internet.
	// If withGOBIN is true, the test will set GOBIN env var.
	// If withGoVersion is set, the test will run assuming the project requires the version.
	// If goForInstall is set, the test will use the go version for 'go install'.
	// If toolsManager is set, goInstallTools will use it instead of the default tools Manager.
	async function runTest(
		testCases: installationTestCase[],
		withLocalProxy?: boolean,
		withGOBIN?: boolean,
		withGoVersion?: string,
		goVersionForInstall?: GoVersion,
		toolsManager?: goInstallTools.IToolsManager
	) {
		const gobin = withLocalProxy && withGOBIN ? path.join(tmpToolsGopath, 'gobin') : undefined;

		let proxyDir: string | undefined;
		let configStub: sinon.SinonStub;
		if (withLocalProxy) {
			proxyDir = buildFakeProxy(testCases);
			const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
				toolsEnvVars: {
					value: {
						GOPROXY: url.pathToFileURL(proxyDir),
						GOSUMDB: 'off',
						GOBIN: gobin,
						// Build environment may have GOMODCACHE set. Avoid writing
						// fake data to it.
						GOMODCACHE: path.join(tmpToolsGopath, 'pkg', 'mod')
					}
				},
				gopath: { value: toolsGopath }
			});
			configStub = sandbox.stub(config, 'getGoConfig').returns(goConfig);
		} else {
			const goConfig = Object.create(vscode.workspace.getConfiguration('go'), {
				toolsEnvVars: {
					value: { GOBIN: gobin }
				},
				gopath: { value: toolsGopath }
			});
			configStub = sandbox.stub(config, 'getGoConfig').returns(goConfig);
		}

		const missingTools = testCases.map((tc) => getToolAtVersion(tc.name));
		const goBinary = getBinPath('go');
		const goVersion = withGoVersion
			? /* we want a fake go version, but need the real 'go' binary to run `go install` */
			  new GoVersion(goBinary, `go version ${withGoVersion} linux/amd64`)
			: await getGoVersion();

		sandbox.stub(vscode.commands, 'executeCommand').withArgs('go.languageserver.restart');
		sandbox
			.stub(goInstallTools, 'getGoVersionForInstall')
			.returns(Promise.resolve(goVersionForInstall ?? goVersion));

		const opts = toolsManager ? { toolsManager } : undefined;
		const failures = await installTools(missingTools, goVersion, opts);
		assert(!failures || failures.length === 0, `installTools failed: ${JSON.stringify(failures)}`);

		// Confirm that each expected tool has been installed.
		const checks: Promise<void>[] = [];
		const exists = util.promisify(fs.exists);
		for (const tc of testCases) {
			checks.push(
				new Promise<void>(async (resolve) => {
					// Check that the expect tool has been installed to $GOPATH/bin.
					const bin = gobin
						? path.join(gobin, correctBinname(tc.name))
						: path.join(tmpToolsGopath, 'bin', correctBinname(tc.name));
					const ok = await exists(bin);
					if (!ok) {
						assert.fail(`expected ${bin}, not found`);
					}
					// If wantVersion is set, check if wanted version was installed.
					if (tc.wantVersion !== undefined) {
						const { moduleVersion } = await inspectGoToolVersion(bin);
						assert.strictEqual(
							moduleVersion,
							tc.wantVersion,
							`expected ${tc.name}@${tc.wantVersion}, got ${moduleVersion}`
						);
					}
					return resolve();
				})
			);
		}
		await Promise.all(checks);

		if (withLocalProxy) {
			sandbox.assert.calledWith(configStub);
			// proxyDir should be set when withLocalProxy = true
			assert(proxyDir);
			rmdirRecursive(proxyDir);
		}
	}

	test('Install one tool with a local proxy', async function () {
		// TODO(golang/vscode-go#3454): reenable the test for old go.
		const systemGoVersion = await getGoVersion();
		if (systemGoVersion.lt('1.21')) {
			this.skip();
		}
		await runTest(
			[
				{
					name: 'gopls',
					versions: ['v0.1.0', 'v1.0.0', 'v1.0.1-pre.2'],
					wantVersion: config.extensionInfo.isPreview ? 'v1.0.1-pre.2' : 'v1.0.0'
				}
			],
			true
		);
	});

	test('Install multiple tools with a local proxy', async function () {
		// TODO(golang/vscode-go#3454): reenable the test for old go.
		const systemGoVersion = await getGoVersion();
		if (systemGoVersion.lt('1.21')) {
			this.skip();
		}
		await runTest(
			[
				{ name: 'gopls', versions: ['v0.1.0', 'v1.0.0-pre.1', 'v1.0.0'], wantVersion: 'v1.0.0' },
				{ name: 'dlv', versions: ['v1.0.0', 'v1.8.0'], wantVersion: 'v1.8.0' }
			],
			true
		);
	});

	test('Install multiple tools with a local proxy & GOBIN', async function () {
		// TODO(golang/vscode-go#3454): reenable the test for old go.
		const systemGoVersion = await getGoVersion();
		if (systemGoVersion.lt('1.21')) {
			this.skip();
		}
		await runTest(
			[
				{ name: 'gopls', versions: ['v0.1.0', 'v1.0.0-pre.1', 'v1.0.0'], wantVersion: 'v1.0.0' },
				{ name: 'dlv', versions: ['v1.0.0', 'v1.8.0'], wantVersion: 'v1.8.0' }
			],
			true, // LOCAL PROXY
			true // GOBIN
		);
	});

	test('Try to install with old go', async () => {
		const oldGo = new GoVersion(getBinPath('go'), 'go version go1.20 amd64/linux');
		sandbox.stub(goInstallTools, 'getGoVersionForInstall').returns(Promise.resolve(oldGo));
		const failures = await installTools([getToolAtVersion('gopls')], oldGo);
		assert(failures?.length === 1 && failures[0].tool.name === 'gopls' && failures[0].reason.includes('or newer'));
	});

	const gofumptDefault = allToolsInformation.get('gofumpt')!.defaultVersion!;
	test('Install gofumpt with old go', async () => {
		await runTest(
			[{ name: 'gofumpt', versions: ['v0.5.0', 'v0.6.0', gofumptDefault], wantVersion: 'v0.6.0' }],
			true, // LOCAL PROXY
			true, // GOBIN
			'go1.21' // Go Version
		);
	});
	test('Install gofumpt with new go', async () => {
		await runTest(
			[{ name: 'gofumpt', versions: ['v0.4.7', 'v0.5.0', gofumptDefault], wantVersion: gofumptDefault }],
			true, // LOCAL PROXY
			true, // GOBIN
			'go1.23.0' // Go Version
		);
	});

	test('Install a tool, with go for install', async () => {
		const systemGoVersion = await getGoVersion();
		const wantGoForInstall = new GoVersion(systemGoVersion.binaryPath, 'go version go1.99.0 linux/amd64');
		const tm: IToolsManager = {
			getMissingTools: () => {
				assert.fail('must not be called');
			},
			installTool: (tool, goVersionForInstall, env) => {
				// Assert the go install command is what we expect.
				assert.strictEqual(tool.name, 'gopls');
				assert.strictEqual(goVersionForInstall, wantGoForInstall);
				assert(env['GOTOOLCHAIN'], `go${systemGoVersion.format()}+auto`);
				// runTest checks if the tool build succeeds. So, delegate the remaining
				// build task to the default tools manager's installTool function.
				return defaultToolsManager.installTool(tool, systemGoVersion, env);
			}
		};
		await runTest(
			[{ name: 'gopls', versions: ['v0.1.0', 'v1.0.0'], wantVersion: 'v1.0.0' }],
			true, // LOCAL PROXY
			true, // GOBIN
			'go' + systemGoVersion.format(true), // Go Version
			wantGoForInstall, // Go for install
			tm // stub installTool to
		);
	});

	test('Install all tools via GOPROXY', async () => {
		// Only run this test if we are in CI before a Nightly release.
		if (!shouldRunSlowTests()) {
			return;
		}
		const goVersion = await getGoVersion();

		const tools: string[] = [];
		for (const [name, info] of allToolsInformation) {
			const minGoVersion = info.minimumGoVersion;
			if (!minGoVersion || goVersion.gt(minGoVersion.format())) {
				tools.push(name);
			}
		}
		assert(tools.includes('gopls') && tools.includes('dlv'), `selected tools ${JSON.stringify(tools)}`);
		await runTest(
			tools.map((tool) => {
				return { name: tool };
			})
		);
	});
});

// buildFakeProxy creates a fake file-based proxy used for testing. The code is
// mostly adapted from golang.org/x/tools/internal/proxydir/proxydir.go.
function buildFakeProxy(testCases: installationTestCase[]) {
	const proxyDir = fs.mkdtempSync(path.join(os.tmpdir(), 'proxydir'));
	for (const tc of testCases) {
		const tool: Tool = getTool(tc.name)!;
		const module = tool.modulePath;
		const pathInModule =
			tool.modulePath === tool.importPath ? '' : tool.importPath.slice(tool.modulePath.length + 1) + '/';
		const versions = tc.versions ?? ['v1.0.0']; // hardcoded for now
		const dir = path.join(proxyDir, module, '@v');
		fs.mkdirSync(dir, { recursive: true });

		// Write the list file.
		fs.writeFileSync(path.join(dir, 'list'), `${versions.join('\n')}\n`);

		versions.map((version) => {
			if (!version.match(/^v\d+\.\d+\.\d+/)) {
				// for tools that retrieve the versions from a revision (commit hash)
				const resolvedVersion = tool.latestVersion?.toString() || '1.0.0';
				const infoPath = path.join(dir, `${version}.info`);
				version = `v${resolvedVersion}`;
				fs.writeFileSync(infoPath, `{ "Version": "${version}", "Time": "2020-04-07T14:45:07Z" } `);
			}

			// Write the go.mod file.
			fs.writeFileSync(path.join(dir, `${version}.mod`), `module ${module}\n`);
			// Write the info file.
			fs.writeFileSync(
				path.join(dir, `${version}.info`),
				`{ "Version": "${version}", "Time": "2020-04-07T14:45:07Z" } `
			);

			// Write the zip file.
			const zip = new AdmZip();
			const content = 'package main; func main() {};';
			zip.addFile(`${module}@${version}/${pathInModule}main.go`, Buffer.alloc(content.length, content));
			zip.writeZip(path.join(dir, `${version}.zip`));
		});
	}
	return proxyDir;
}

// Check if VSCODEGO_BEFORE_RELEASE_TESTS is set to true. This environment
// variable is set by the CI system that releases the Nightly extension,
// allowing us to opt-in to more rigorous testing only before releases.
function shouldRunSlowTests(): boolean {
	return !!process.env['VSCODEGO_BEFORE_RELEASE_TESTS'];
}

suite('getRequiredTools', () => {
	const testCases: {
		name: string;
		goConfig: Map<string, any>;
		expectedTools: string[];
	}[] = [
		{
			name: 'include gopls when {"go.useLanguageServer": true}',
			goConfig: new Map<string, any>([['useLanguageServer', true]]),
			// exclude third party tool that is replaced by gopls
			expectedTools: ['gopls', 'dlv', 'gotests', 'impl', 'goplay']
		},
		{
			name: 'exclude gopls when {"go.useLanguageServer": true}',
			goConfig: new Map<string, any>([['useLanguageServer', false]]),
			expectedTools: [
				'dlv',
				'impl',
				'goplay',
				// include third party tool that is replaced by gopls
				'gomodifytags',
				'gotests'
			]
		},
		{
			name: 'include golangci-lint specified in "go.lintTool"',
			goConfig: new Map<string, any>([
				['useLanguageServer', true],
				['lintTool', 'golangci-lint']
			]),
			expectedTools: ['golangci-lint', 'gopls', 'dlv', 'gotests', 'impl', 'goplay']
		}
	];

	for (const tc of testCases) {
		test(tc.name, async () => {
			const configured = getRequiredTools(new MockWorkspaceConfiguration(getGoConfig(), tc.goConfig));
			const got = configured.map((tool) => tool.name) ?? [];
			assert.deepStrictEqual(got.sort(), tc.expectedTools.sort());
		});
	}
});

function fakeGoVersion(versionStr: string) {
	return new GoVersion('/path/to/go', versionStr);
}

suite('listOutdatedTools', () => {
	let sandbox: sinon.SinonSandbox;
	setup(() => {
		sandbox = sinon.createSandbox();
	});
	teardown(() => sandbox.restore());

	// goVersion: go toolchain's version
	// tools: toolname -> go toolchain version used to compile the tool
	async function runTest(goVersion: string | undefined, tools: { [key: string]: string | undefined }) {
		const binPathStub = sandbox.stub(utilModule, 'getBinPath');
		const versionStub = sandbox.stub(goInstallTools, 'inspectGoToolVersion');
		for (const tool in tools) {
			binPathStub.withArgs(tool).returns(`/bin/${tool}`);
			versionStub.withArgs(`/bin/${tool}`).returns(Promise.resolve({ goVersion: tools[tool] }));
		}

		const toolsToCheck = Object.keys(tools).map((tool) => getToolAtVersion(tool));

		const configuredGoVersion = goVersion ? fakeGoVersion(goVersion) : undefined;
		const toolsToUpdate = await goInstallTools.listOutdatedTools(configuredGoVersion, toolsToCheck);
		return toolsToUpdate.map((tool) => tool.name).filter((tool) => !!tool);
	}

	test('minor version difference requires updates', async () => {
		const x = await runTest('go version go1.23.0 linux/amd64', {
			gopls: 'go1.22.2',
			dlv: 'go1.21.0',
			staticcheck: 'go1.23.0',
			gotests: 'go1.24.1'
		});
		assert.deepStrictEqual(x, ['gopls', 'dlv']);
	});
	test('patch version difference does not require updates', async () => {
		const x = await runTest('go version go1.23.1 linux/amd64', {
			gopls: 'go1.23.0', // 1.16 < 1.16.1
			dlv: 'go1.23.1', // 1.16.1 == 1.16.1
			staticcheck: 'go1.23.2', // 1.16.2 > 1.16.1
			gotests: 'go1.23rc1' // go1.23rc1 != go1.23.0
		});
		assert.deepStrictEqual(x, ['gotests']);
	});
	test('go is rc version', async () => {
		const x = await runTest('go version go1.23rc2 linux/amd64', {
			gopls: 'go1.22.3', // go1.22.3 < go1.23rc2
			dlv: 'go1.23rc1', // go1.23rc1 < go1.23rc2
			staticcheck: 'go1.23rc2', // same
			gotests: 'go1.23.0' // go1.23rc2 < go1.23.0
		});
		assert.deepStrictEqual(x, ['gopls', 'dlv']);
	});
	test('go is dev version - skip version check', async () => {
		const x = await runTest('go version devel go1.24-41f485b9a7 linux/amd64', {
			gopls: 'go1.13.1',
			dlv: 'go1.24rc1',
			staticcheck: 'go1.23.0',
			gotests: 'go1.24.0'
		});
		assert.deepStrictEqual(x, []);
	});
	test('go is unknown version - skip version check', async () => {
		const x = await runTest('', {
			gopls: 'go1.23.1'
		});
		assert.deepStrictEqual(x, []);
	});
	test('tools are unknown versions', async () => {
		const x = await runTest('go version go1.22.0 linux/amd64', {
			gopls: undefined, // this can be because gopls was compiled with go1.18 or it's too old.
			dlv: 'go1.20'
		});
		assert.deepStrictEqual(x, ['gopls', 'dlv']);
	});
});

suite('maybeInstallImportantTools tests', () => {
	let sandbox: sinon.SinonSandbox;

	setup(() => {
		sandbox = sinon.createSandbox();
	});

	teardown(async () => sandbox.restore());

	// runTest actually executes the logic of the test using a fake proxy.
	async function runTest(
		toolsManager: goInstallTools.IToolsManager,
		alternateToolsCfg: { [key: string]: string } = {},
		wantMissingTools: string[] = []
	) {
		// maybeInstallImportantTools shouldn't trigger gopls restart.
		// The caller ('activate') will explicitly start it.
		sandbox
			.stub(vscode.commands, 'executeCommand')
			.withArgs('go.languageserver.restart')
			.throws(new Error('gopls shouldn not be restarted'));

		try {
			const statusBarItem = await maybeInstallImportantTools(alternateToolsCfg, toolsManager);
			assert.strictEqual(statusBarItem.busy, false);
			assert.strictEqual(
				statusBarItem.severity,
				wantMissingTools && wantMissingTools.length > 0
					? vscode.LanguageStatusSeverity.Error
					: vscode.LanguageStatusSeverity.Information,
				statusBarItem.text
			);
			if (wantMissingTools && wantMissingTools.length > 0) {
				assert.strictEqual(statusBarItem.command?.title, 'Install missing tools');
				for (const tool of wantMissingTools) {
					assert(statusBarItem.detail!.includes(tool), statusBarItem.detail + ' does not contain ' + tool);
				}
			} else {
				assert.strictEqual(statusBarItem.command?.title, 'Update');
				assert.strictEqual(statusBarItem.detail, 'no missing tools');
			}
		} catch (e) {
			assert.fail(`maybeInstallImportantTools failed: ${e}`);
		}
	}

	test('Successfully install gopls & linter', async () => {
		await runTest(
			mockToolsManager(['gopls', 'staticcheck']),
			{}, // emtpry alternateTools.
			[] // no missing tools after run.
		);
	});

	test('Do not install alternate tools', async () => {
		await runTest(mockToolsManager(['gopls', 'staticcheck']), { gopls: 'fork.example.com/gopls' }, ['gopls']);
	});

	test('Recover when installation fails', async () => {
		const tm = mockToolsManager(['gopls', 'staticcheck']);
		tm.installTool = () => {
			return Promise.resolve('failed');
		};
		await runTest(tm, {}, ['gopls', 'staticcheck']);
	});

	test('Recover when installation crashes', async () => {
		const tm = mockToolsManager(['gopls', 'staticcheck']);
		tm.installTool = () => {
			throw new Error('crash');
		};
		await runTest(tm, {}, ['gopls', 'staticcheck']);
	});

	/**
	 * Creates a mock IToolsManager for testing purposes. Both method can be
	 * overwritten in test to control the manager behavior.
	 *
	 * @param requiredTools An array of tool names that this mock manager
	 * should treat as its universe of known tools for the test.
	 * @returns A mock object that implements the IToolsManager interface.
	 */
	function mockToolsManager(requiredTools: string[] = []) {
		const installed: string[] = [];

		const toolsManager: goInstallTools.IToolsManager = {
			getMissingTools: function (matcher: (tool: Tool) => boolean): Promise<Tool[]> {
				let tools: Tool[] = requiredTools.map((t) => {
					return allToolsInformation.get(t)!;
				});
				// apply user's filter;
				tools = matcher ? tools.filter(matcher) : tools;
				// remove tools that are installed.
				tools = tools.filter((tool) => !installed.includes(tool.name));
				return Promise.resolve(tools);
			},
			installTool: function (tool: Tool): Promise<string | undefined> {
				installed.push(tool.name);
				return Promise.resolve(undefined); // no error.
			}
		};

		return toolsManager;
	}
});
