import type { TextEditor, Uri } from 'vscode';
import { Logger } from '@gitlens/utils/logger.js';
import type { Container } from '../container.js';
import { GitUri } from '../git/gitUri.js';
import { getBranchAssociatedPullRequest } from '../git/utils/-webview/branch.utils.js';
import { getBestRemoteWithIntegration } from '../git/utils/-webview/remote.utils.js';
import { getRepositoryOrShowPicker } from '../quickpicks/repositoryPicker.js';
import { command, executeCommand } from '../system/-webview/command.js';
import { ActiveEditorCommand } from './commandBase.js';
import { getCommandUri } from './commandBase.utils.js';
import type { OpenPullRequestOnRemoteCommandArgs } from './openPullRequestOnRemote.js';

@command()
export class OpenAssociatedPullRequestOnRemoteCommand extends ActiveEditorCommand {
	constructor(private readonly container: Container) {
		super('gitlens.openAssociatedPullRequestOnRemote');
	}

	async execute(editor?: TextEditor, uri?: Uri): Promise<void> {
		uri = getCommandUri(uri, editor);

		const gitUri = uri != null ? await GitUri.fromUri(uri) : undefined;

		let args: OpenPullRequestOnRemoteCommandArgs;
		if (editor != null && gitUri != null) {
			const blameline = editor.selection.active.line;
			if (blameline < 0) return;

			try {
				const blame = await this.container.git.getBlameForLine(gitUri, blameline);
				if (blame == null) return;

				args = { clipboard: false, ref: blame.commit.sha, repoPath: blame.commit.repoPath };
			} catch (ex) {
				Logger.error(ex, 'OpenAssociatedPullRequestOnRemoteCommand', `getBlameForLine(${blameline})`);
				return;
			}
		} else {
			try {
				const repo = await getRepositoryOrShowPicker(
					this.container,
					'Open Associated Pull Request',
					undefined,
					undefined,
					{
						filter: async r => (await getBestRemoteWithIntegration(r.path)) != null,
					},
				);
				if (repo == null) return;

				const branch = await repo?.git.branches.getBranch();
				const pr =
					branch != null
						? await getBranchAssociatedPullRequest(this.container, branch, { expiryOverride: true })
						: undefined;

				args =
					pr != null
						? { clipboard: false, pr: { url: pr.url } }
						: { clipboard: false, ref: branch?.name ?? 'HEAD', repoPath: repo.path };
			} catch (ex) {
				Logger.error(ex, 'OpenAssociatedPullRequestOnRemoteCommand', 'No editor opened');
				return;
			}
		}

		await executeCommand<OpenPullRequestOnRemoteCommandArgs>('gitlens.openPullRequestOnRemote', args);
	}
}
