import type { Cache } from '@gitlens/git/cache.js';
import type { GitUser } from '@gitlens/git/models/user.js';
import type { GitConfigSubProvider } from '@gitlens/git/providers/config.js';
import { gate } from '@gitlens/utils/decorators/gate.js';
import { debug } from '@gitlens/utils/decorators/log.js';
import { getScopedLogger } from '@gitlens/utils/logger.scoped.js';
import { toTokenInfo } from '../../api/tokenUtils.js';
import type { GitHubGitProviderInternal } from '../githubProvider.js';

export class ConfigGitSubProvider implements GitConfigSubProvider {
	constructor(
		private readonly cache: Cache,
		private readonly provider: GitHubGitProviderInternal,
	) {}

	@gate()
	@debug()
	async getCurrentUser(repoPath: string): Promise<GitUser | undefined> {
		if (!repoPath) return undefined;

		const scope = getScopedLogger();

		const cached = this.cache.currentUser.get(repoPath);
		if (cached != null) return cached;
		// If we found null, user data was not found - don't bother trying again
		if (cached === null) return undefined;

		try {
			const { metadata, github, session } = await this.provider.ensureRepositoryContext(repoPath);
			const user = await github.getCurrentUser(
				toTokenInfo(this.provider.authenticationProviderId, session),
				metadata.repo.owner,
				metadata.repo.name,
			);

			this.cache.currentUser.set(repoPath, user ?? null);
			return user;
		} catch (ex) {
			scope?.error(ex);
			debugger;

			// Mark it so we won't bother trying again
			this.cache.currentUser.set(repoPath, null);
			return undefined;
		}
	}
}
