/* eslint-disable node/no-unpublished-import */
/*---------------------------------------------------------
 * Copyright 2023 The Go Authors. All rights reserved.
 * Licensed under the MIT License. See LICENSE in the project root for license information.
 *--------------------------------------------------------*/

import * as sinon from 'sinon';
import { describe, it } from 'mocha';
import {
	GOPLS_MAYBE_PROMPT_FOR_TELEMETRY,
	TELEMETRY_START_TIME_KEY,
	TelemetryReporter,
	TelemetryService,
	recordTelemetryStartTime
} from '../../src/goTelemetry';
import { MockMemento } from '../mocks/MockMemento';
import { maybeInstallVSCGO } from '../../src/goInstallTools';
import assert from 'assert';
import path from 'path';
import * as fs from 'fs-extra';
import os = require('os');
import { rmdirRecursive } from '../../src/util';
import { extensionId } from '../../src/const';
import { executableFileExists, fileExists } from '../../src/utils/pathUtils';
import { ExtensionMode, Memento, extensions } from 'vscode';

describe('# prompt for telemetry', async () => {
	const extension = extensions.getExtension(extensionId);
	assert(extension);

	it(
		'do not prompt if language client is not used',
		testTelemetryPrompt(
			{
				noLangClient: true,
				previewExtension: true,
				samplingInterval: 1000
			},
			false
		)
	); // no crash when there is no language client.
	it(
		'do not prompt if gopls does not support telemetry',
		testTelemetryPrompt(
			{
				goplsWithoutTelemetry: true,
				previewExtension: true,
				samplingInterval: 1000
			},
			false
		)
	);
	it(
		'prompt when telemetry started a while ago',
		testTelemetryPrompt(
			{
				firstDate: new Date('2022-01-01'),
				samplingInterval: 1000
			},
			true
		)
	);
	it(
		'do not prompt if telemetry started two days ago',
		testTelemetryPrompt(
			{
				firstDate: new Date(Date.now() - 2 * 24 * 60 * 60 * 1000), // two days ago!
				samplingInterval: 1000
			},
			false
		)
	);
	it(
		'do not prompt if gopls with telemetry never ran',
		testTelemetryPrompt(
			{
				firstDate: undefined, // gopls with telemetry not seen before.
				samplingInterval: 1000
			},
			false
		)
	);
	it(
		'do not prompt if not sampled',
		testTelemetryPrompt(
			{
				firstDate: new Date('2022-01-01'),
				samplingInterval: 0
			},
			false
		)
	);
	it(
		'prompt only if sampled (machineID = 0, samplingInterval = 1)',
		testTelemetryPrompt(
			{
				firstDate: new Date('2022-01-01'),
				samplingInterval: 1,
				hashMachineID: 0
			},
			true
		)
	);
	it(
		'prompt only if sampled (machineID = 1, samplingInterval = 1)',
		testTelemetryPrompt(
			{
				firstDate: new Date('2022-01-01'),
				samplingInterval: 1,
				hashMachineID: 1
			},
			false
		)
	);
	it(
		'prompt all preview extension users',
		testTelemetryPrompt(
			{
				firstDate: new Date('2022-01-01'),
				previewExtension: true,
				samplingInterval: 0
			},
			true
		)
	);
	it(
		'do not prompt if vscode telemetry is disabled',
		testTelemetryPrompt(
			{
				firstDate: new Date('2022-01-01'),
				vsTelemetryDisabled: true,
				previewExtension: true,
				samplingInterval: 1000
			},
			false
		)
	);
	// testExtensionAPI.globalState is a real memento instance passed by ExtensionHost.
	// This instance is active throughout the integration test.
	// When you add more test cases that interact with the globalState,
	// be aware that multiple test cases may access and mutate it asynchronously.
	const testExtensionAPI = await extension.activate();
	it('check we can salvage the value in the real memento', async () => {
		// write Date with Memento.update - old way. Now we always use string for TELEMETRY_START_TIME_KEY value.
		testExtensionAPI.globalState.update(TELEMETRY_START_TIME_KEY, new Date(Date.now() - 7 * 24 * 60 * 60 * 1000));
		await testTelemetryPrompt(
			{
				samplingInterval: 1000,
				mementoInstance: testExtensionAPI.globalState
			},
			true
		)();
	});
});

interface testCase {
	noLangClient?: boolean; // gopls is not running.
	goplsWithoutTelemetry?: boolean; // gopls is too old.
	firstDate?: Date; // first date the extension observed gopls with telemetry feature.
	previewExtension?: boolean; // assume we are in dev/nightly extension.
	vsTelemetryDisabled?: boolean; // assume the user disabled vscode general telemetry.
	samplingInterval: number; // N where N out of 1000 are sampled.
	hashMachineID?: number; // stub the machine id hash computation function.
	mementoInstance?: Memento; // if set, use this instead of mock memento.
}

function testTelemetryPrompt(tc: testCase, wantPrompt: boolean) {
	return async () => {
		const languageClient = {
			sendRequest: () => {
				return Promise.resolve();
			}
		};
		const spy = sinon.spy(languageClient, 'sendRequest');
		const lc = tc.noLangClient ? undefined : languageClient;

		const memento = tc.mementoInstance ?? new MockMemento();
		if (tc.firstDate) {
			recordTelemetryStartTime(memento, tc.firstDate);
		}
		const commands = tc.goplsWithoutTelemetry ? [] : [GOPLS_MAYBE_PROMPT_FOR_TELEMETRY];

		const sut = new TelemetryService(lc, memento, commands);
		if (tc.hashMachineID !== undefined) {
			sinon.stub(sut, 'hashMachineID').returns(tc.hashMachineID);
		}
		await sut.promptForTelemetry(!!tc.previewExtension, !tc.vsTelemetryDisabled, tc.samplingInterval);
		if (wantPrompt) {
			sinon.assert.calledOnce(spy);
		} else {
			sinon.assert.neverCalledWith(spy);
		}
	};
}

describe('# telemetry reporter using vscgo', async function () {
	this.timeout(10000); // go install can be slow.
	// installVSCGO expects
	//   {extensionPath}/vscgo: vscgo source code for testing.
	//   {extensionPath}/bin: where compiled vscgo will be stored.
	// During testing, extensionDevelopmentPath is the root of the extension.
	// __dirname = out/test/gopls.
	const extensionDevelopmentPath = path.resolve(__dirname, '../../..');
	const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'telemetryReporter'));
	const counterfile = path.join(tmpDir, 'counterfile.txt');
	const sut = new TelemetryReporter(0, counterfile);
	let vscgo: string;

	suiteSetup(async () => {
		try {
			vscgo = await maybeInstallVSCGO(
				ExtensionMode.Test,
				extensionId,
				'',
				extensionDevelopmentPath,
				true /*isPreview*/
			);
		} catch (e) {
			assert.fail(`failed to install vscgo needed for testing: ${e}`);
		}
	});
	suiteTeardown(() => {
		rmdirRecursive(tmpDir);
		if (executableFileExists(vscgo)) {
			fs.unlink(vscgo);
		}
	});

	teardown(() => {
		if (fileExists(counterfile)) {
			fs.unlink(counterfile);
		}
	});

	it('add succeeds before telemetryReporter.setTool runs', () => {
		sut.add('hello', 1);
		sut.add('world', 2);
	});

	it('flush is noop before setTool', async () => {
		await sut.flush();
		assert(!fileExists(counterfile), 'counterfile exists');
	});

	it('flush writes accumulated counters after setTool', async () => {
		sut.setTool(vscgo);
		await sut.flush();
		const readAll = fs.readFileSync(counterfile).toString();
		assert(readAll.includes('hello 1\n') && readAll.includes('world 2\n'), readAll);
	});

	it('dispose triggers flush', async () => {
		sut.add('bye', 3);
		await sut.dispose();
		const readAll = fs.readFileSync(counterfile).toString();
		assert(readAll.includes('bye 3\n'), readAll);
	});
});
