"use strict";
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeGitHubAPIRequest = makeGitHubAPIRequest;
exports.makeGitHubGraphQLRequest = makeGitHubGraphQLRequest;
exports.makeSearchGraphQLRequest = makeSearchGraphQLRequest;
exports.getPullRequestFromGlobalId = getPullRequestFromGlobalId;
exports.addPullRequestCommentGraphQLRequest = addPullRequestCommentGraphQLRequest;
exports.closePullRequest = closePullRequest;
exports.makeGitHubAPIRequestWithPagination = makeGitHubAPIRequestWithPagination;
async function makeGitHubAPIRequest(fetcherService, logService, telemetry, host, routeSlug, method, token, body, version, type = 'json', userAgent) {
    const headers = {
        'Accept': 'application/vnd.github+json',
    };
    if (token) {
        headers['Authorization'] = `Bearer ${token}`;
    }
    if (version) {
        headers['X-GitHub-Api-Version'] = version;
    }
    if (userAgent) {
        headers['User-Agent'] = userAgent;
    }
    const response = await fetcherService.fetch(`${host}/${routeSlug}`, {
        method,
        headers,
        body: body ? JSON.stringify(body) : undefined
    });
    if (!response.ok) {
        return undefined;
    }
    try {
        const result = type === 'json' ? await response.json() : await response.text();
        const rateLimit = Number(response.headers.get('x-ratelimit-remaining'));
        const logMessage = `[RateLimit] REST rate limit remaining: ${rateLimit}, ${routeSlug}`;
        if (rateLimit < 1000) {
            // Danger zone
            logService.warn(logMessage);
            telemetry.sendMSFTTelemetryEvent('githubAPI.approachingRateLimit', { rateLimit: rateLimit.toString() });
        }
        else {
            logService.debug(logMessage);
        }
        return result;
    }
    catch {
        return undefined;
    }
}
async function makeGitHubGraphQLRequest(fetcherService, logService, telemetry, host, query, token, variables) {
    const headers = {
        'Accept': 'application/vnd.github+json',
        'Content-Type': 'application/json',
    };
    if (token) {
        headers['Authorization'] = `Bearer ${token}`;
    }
    const body = JSON.stringify({
        query,
        variables
    });
    const response = await fetcherService.fetch(`${host}/graphql`, {
        method: 'POST',
        headers,
        body
    });
    if (!response.ok) {
        return undefined;
    }
    try {
        const result = await response.json();
        const rateLimit = Number(response.headers.get('x-ratelimit-remaining'));
        const logMessage = `[RateLimit] GraphQL rate limit remaining: ${rateLimit}, query: ${query}`;
        if (rateLimit < 1000) {
            // Danger zone
            logService.warn(logMessage);
            telemetry.sendMSFTTelemetryEvent('githubAPI.approachingRateLimit', { rateLimit: rateLimit.toString() });
        }
        else {
            logService.debug(logMessage);
        }
        return result;
    }
    catch {
        return undefined;
    }
}
async function makeSearchGraphQLRequest(fetcherService, logService, telemetry, host, token, searchQuery, first = 20) {
    const query = `
		query FetchCopilotAgentPullRequests($searchQuery: String!, $first: Int!, $after: String) {
			search(query: $searchQuery, type: ISSUE, first: $first, after: $after) {
				nodes {
					... on PullRequest {
						number
						id
						fullDatabaseId
						headRefOid
						title
						state
						url
						createdAt
						updatedAt
						additions
						deletions
						author {
							login
						}
						repository {
							owner {
								login
							}
							name
						}
						body
					}
				}
				pageInfo {
					hasNextPage
					endCursor
				}
				issueCount
			}
		}
	`;
    logService.debug(`[FolderRepositoryManager+0] Fetch pull request category ${searchQuery}`);
    const variables = {
        searchQuery,
        first
    };
    const result = await makeGitHubGraphQLRequest(fetcherService, logService, telemetry, host, query, token, variables);
    return result ? result.data.search.nodes : [];
}
async function getPullRequestFromGlobalId(fetcherService, logService, telemetry, host, token, globalId) {
    const query = `
		query GetPullRequestGlobal($globalId: ID!) {
			node(id: $globalId) {
				... on PullRequest {
					number
					id
					fullDatabaseId
					headRefOid
					title
					state
					url
					createdAt
					updatedAt
					additions
					deletions
					author {
						login
					}
					repository {
						owner {
							login
						}
						name
					}
					body
				}
			}
		}
	`;
    logService.debug(`[GitHubAPI] Fetch pull request by global ID ${globalId}`);
    const variables = {
        globalId,
    };
    const result = await makeGitHubGraphQLRequest(fetcherService, logService, telemetry, host, query, token, variables);
    return result?.data?.node;
}
async function addPullRequestCommentGraphQLRequest(fetcherService, logService, telemetry, host, token, pullRequestId, commentBody) {
    const mutation = `
		mutation AddPullRequestComment($pullRequestId: ID!, $body: String!) {
			addComment(input: {subjectId: $pullRequestId, body: $body}) {
				commentEdge {
					node {
						id
						body
						createdAt
						author {
							login
						}
						url
					}
				}
			}
		}
	`;
    logService.debug(`[GitHubAPI] Adding comment to pull request ${pullRequestId}`);
    const variables = {
        pullRequestId,
        body: commentBody
    };
    const result = await makeGitHubGraphQLRequest(fetcherService, logService, telemetry, host, mutation, token, variables);
    return result?.data?.addComment?.commentEdge?.node || null;
}
async function closePullRequest(fetcherService, logService, telemetry, host, token, owner, repo, pullNumber) {
    logService.debug(`[GitHubAPI] Closing pull request ${owner}/${repo}#${pullNumber}`);
    const result = await makeGitHubAPIRequest(fetcherService, logService, telemetry, host, `repos/${owner}/${repo}/pulls/${pullNumber}`, 'POST', token, { state: 'closed' }, '2022-11-28');
    const success = result?.state === 'closed';
    if (success) {
        logService.debug(`[GitHubAPI] Successfully closed pull request ${owner}/${repo}#${pullNumber}`);
    }
    else {
        logService.error(`[GitHubAPI] Failed to close pull request ${owner}/${repo}#${pullNumber}. Its state is ${result?.state}`);
    }
    return success;
}
async function makeGitHubAPIRequestWithPagination(fetcherService, logService, host, path, nwo, token) {
    let hasNextPage = false;
    const sessionInfos = [];
    const page_size = 20;
    let page = 1;
    do {
        const response = await fetcherService.fetch(`${host}/${path}?page_size=${page_size}&page_number=${page}&resource_state=draft,open&repo_nwo=${nwo}`, {
            headers: {
                Authorization: `Bearer ${token}`,
                Accept: 'application/json',
            },
        });
        if (!response.ok) {
            logService.error(`[GitHubAPI] Failed to fetch sessions: ${response.status} ${response.statusText}`);
            return sessionInfos;
        }
        const sessions = await response.json();
        sessionInfos.push(...sessions.sessions);
        hasNextPage = sessions.sessions.length === page_size;
        page++;
    } while (hasNextPage);
    return sessionInfos;
}
//# sourceMappingURL=githubAPI.js.map