import type { TextEditor, Uri } from 'vscode';
import { createSearchQueryForCommits } from '@gitlens/git/utils/search.utils.js';
import { filterMap } from '@gitlens/utils/iterable.js';
import { Logger } from '@gitlens/utils/logger.js';
import type { Container } from '../container.js';
import { executeGitCommand } from '../git/actions.js';
import { GitUri } from '../git/gitUri.js';
import { showFileNotUnderSourceControlWarningMessage, showGenericErrorMessage } from '../messages.js';
import { command } from '../system/-webview/command.js';
import { createMarkdownCommandLink } from '../system/commands.js';
import { ActiveEditorCommand } from './commandBase.js';
import { getCommandUri } from './commandBase.utils.js';

export interface ShowCommitsInViewCommandArgs {
	refs?: string[];
	repoPath?: string;
}

@command()
export class ShowCommitsInViewCommand extends ActiveEditorCommand {
	static createMarkdownCommandLink(sha: string, repoPath: string): string;
	static createMarkdownCommandLink(args: ShowCommitsInViewCommandArgs): string;
	static createMarkdownCommandLink(argsOrSha: ShowCommitsInViewCommandArgs | string, repoPath?: string): string {
		const args = typeof argsOrSha === 'string' ? { refs: [argsOrSha], repoPath: repoPath } : argsOrSha;
		return createMarkdownCommandLink<ShowCommitsInViewCommandArgs>('gitlens.showCommitsInView', args);
	}

	constructor(private readonly container: Container) {
		super('gitlens.showCommitsInView');
	}

	async execute(editor?: TextEditor, uri?: Uri, args?: ShowCommitsInViewCommandArgs): Promise<void> {
		args = { ...args };

		if (args.refs == null) {
			uri = getCommandUri(uri, editor);
			if (uri == null) return undefined;

			const gitUri = await GitUri.fromUri(uri);

			args.repoPath = gitUri.repoPath;

			if (editor != null) {
				try {
					// Check for any uncommitted changes in the range
					const blame = editor.document.isDirty
						? await this.container.git.getBlameForRangeContents(
								gitUri,
								editor.selection,
								editor.document.getText(),
							)
						: await this.container.git.getBlameForRange(gitUri, editor.selection);
					if (blame === undefined) {
						return void showFileNotUnderSourceControlWarningMessage('Unable to find commits');
					}

					args.refs = [...filterMap(blame.commits.values(), c => (c.isUncommitted ? undefined : c.ref))];
				} catch (ex) {
					Logger.error(ex, 'ShowCommitsInViewCommand', 'getBlameForRange');
					return void showGenericErrorMessage('Unable to find commits');
				}
			} else {
				if (gitUri.sha == null) return undefined;

				args.refs = [gitUri.sha];
			}
		}

		// if (args.refs.length === 1) {
		// 	return showDetailsView(createReference(args.refs[0], args.repoPath!, { refType: 'revision' }));
		// }

		return executeGitCommand({
			command: 'search',
			state: {
				repo: args?.repoPath,
				query: createSearchQueryForCommits(args.refs),
				showResultsInSideBar: true,
			},
		});
	}
}
