#!/usr/bin/env node

async function githubRequest(endpoint, token, method = 'GET', body) {
	const response = await fetch(`https://api.github.com${endpoint}`, {
		method,
		headers: {
			Authorization: `Bearer ${token}`,
			Accept: 'application/vnd.github.v3+json',
			'User-Agent': 'auto-close-duplicates-script',
			...(body && { 'Content-Type': 'application/json' })
		},
		...(body && { body: JSON.stringify(body) })
	});

	if (!response.ok) {
		throw new Error(
			`GitHub API request failed: ${response.status} ${response.statusText}`
		);
	}

	return response.json();
}

function extractDuplicateIssueNumber(commentBody) {
	const match = commentBody.match(/#(\d+)/);
	return match ? parseInt(match[1], 10) : null;
}

async function closeIssueAsDuplicate(
	owner,
	repo,
	issueNumber,
	duplicateOfNumber,
	token
) {
	await githubRequest(
		`/repos/${owner}/${repo}/issues/${issueNumber}`,
		token,
		'PATCH',
		{
			state: 'closed',
			state_reason: 'not_planned',
			labels: ['duplicate']
		}
	);

	await githubRequest(
		`/repos/${owner}/${repo}/issues/${issueNumber}/comments`,
		token,
		'POST',
		{
			body: `This issue has been automatically closed as a duplicate of #${duplicateOfNumber}.

If this is incorrect, please re-open this issue or create a new one.

🤖 Generated with [Task Master Bot]`
		}
	);
}

async function autoCloseDuplicates() {
	console.log('[DEBUG] Starting auto-close duplicates script');

	const token = process.env.GITHUB_TOKEN;
	if (!token) {
		throw new Error('GITHUB_TOKEN environment variable is required');
	}
	console.log('[DEBUG] GitHub token found');

	const owner = process.env.GITHUB_REPOSITORY_OWNER || 'eyaltoledano';
	const repo = process.env.GITHUB_REPOSITORY_NAME || 'claude-task-master';
	console.log(`[DEBUG] Repository: ${owner}/${repo}`);

	const threeDaysAgo = new Date();
	threeDaysAgo.setDate(threeDaysAgo.getDate() - 3);
	console.log(
		`[DEBUG] Checking for duplicate comments older than: ${threeDaysAgo.toISOString()}`
	);

	console.log('[DEBUG] Fetching open issues created more than 3 days ago...');
	const allIssues = [];
	let page = 1;
	const perPage = 100;

	const MAX_PAGES = 50; // Increase limit for larger repos
	let foundRecentIssue = false;

	while (true) {
		const pageIssues = await githubRequest(
			`/repos/${owner}/${repo}/issues?state=open&per_page=${perPage}&page=${page}&sort=created&direction=desc`,
			token
		);

		if (pageIssues.length === 0) break;

		// Filter for issues created more than 3 days ago
		const oldEnoughIssues = pageIssues.filter(
			(issue) => new Date(issue.created_at) <= threeDaysAgo
		);

		allIssues.push(...oldEnoughIssues);

		// If all issues on this page are newer than 3 days, we can stop
		if (oldEnoughIssues.length === 0 && page === 1) {
			foundRecentIssue = true;
			break;
		}

		// If we found some old issues but not all, continue to next page
		// as there might be more old issues
		page++;

		// Safety limit to avoid infinite loops
		if (page > MAX_PAGES) {
			console.log(`[WARNING] Reached maximum page limit of ${MAX_PAGES}`);
			break;
		}
	}

	const issues = allIssues;
	console.log(`[DEBUG] Found ${issues.length} open issues`);

	let processedCount = 0;
	let candidateCount = 0;

	for (const issue of issues) {
		processedCount++;
		console.log(
			`[DEBUG] Processing issue #${issue.number} (${processedCount}/${issues.length}): ${issue.title}`
		);

		console.log(`[DEBUG] Fetching comments for issue #${issue.number}...`);
		const comments = await githubRequest(
			`/repos/${owner}/${repo}/issues/${issue.number}/comments`,
			token
		);
		console.log(
			`[DEBUG] Issue #${issue.number} has ${comments.length} comments`
		);

		const dupeComments = comments.filter(
			(comment) =>
				comment.body.includes('Found') &&
				comment.body.includes('possible duplicate') &&
				comment.user.type === 'Bot'
		);
		console.log(
			`[DEBUG] Issue #${issue.number} has ${dupeComments.length} duplicate detection comments`
		);

		if (dupeComments.length === 0) {
			console.log(
				`[DEBUG] Issue #${issue.number} - no duplicate comments found, skipping`
			);
			continue;
		}

		const lastDupeComment = dupeComments[dupeComments.length - 1];
		const dupeCommentDate = new Date(lastDupeComment.created_at);
		console.log(
			`[DEBUG] Issue #${
				issue.number
			} - most recent duplicate comment from: ${dupeCommentDate.toISOString()}`
		);

		if (dupeCommentDate > threeDaysAgo) {
			console.log(
				`[DEBUG] Issue #${issue.number} - duplicate comment is too recent, skipping`
			);
			continue;
		}
		console.log(
			`[DEBUG] Issue #${
				issue.number
			} - duplicate comment is old enough (${Math.floor(
				(Date.now() - dupeCommentDate.getTime()) / (1000 * 60 * 60 * 24)
			)} days)`
		);

		const commentsAfterDupe = comments.filter(
			(comment) => new Date(comment.created_at) > dupeCommentDate
		);
		console.log(
			`[DEBUG] Issue #${issue.number} - ${commentsAfterDupe.length} comments after duplicate detection`
		);

		if (commentsAfterDupe.length > 0) {
			console.log(
				`[DEBUG] Issue #${issue.number} - has activity after duplicate comment, skipping`
			);
			continue;
		}

		console.log(
			`[DEBUG] Issue #${issue.number} - checking reactions on duplicate comment...`
		);
		const reactions = await githubRequest(
			`/repos/${owner}/${repo}/issues/comments/${lastDupeComment.id}/reactions`,
			token
		);
		console.log(
			`[DEBUG] Issue #${issue.number} - duplicate comment has ${reactions.length} reactions`
		);

		const authorThumbsDown = reactions.some(
			(reaction) =>
				reaction.user.id === issue.user.id && reaction.content === '-1'
		);
		console.log(
			`[DEBUG] Issue #${issue.number} - author thumbs down reaction: ${authorThumbsDown}`
		);

		if (authorThumbsDown) {
			console.log(
				`[DEBUG] Issue #${issue.number} - author disagreed with duplicate detection, skipping`
			);
			continue;
		}

		const duplicateIssueNumber = extractDuplicateIssueNumber(
			lastDupeComment.body
		);
		if (!duplicateIssueNumber) {
			console.log(
				`[DEBUG] Issue #${issue.number} - could not extract duplicate issue number from comment, skipping`
			);
			continue;
		}

		candidateCount++;
		const issueUrl = `https://github.com/${owner}/${repo}/issues/${issue.number}`;

		try {
			console.log(
				`[INFO] Auto-closing issue #${issue.number} as duplicate of #${duplicateIssueNumber}: ${issueUrl}`
			);
			await closeIssueAsDuplicate(
				owner,
				repo,
				issue.number,
				duplicateIssueNumber,
				token
			);
			console.log(
				`[SUCCESS] Successfully closed issue #${issue.number} as duplicate of #${duplicateIssueNumber}`
			);
		} catch (error) {
			console.error(
				`[ERROR] Failed to close issue #${issue.number} as duplicate: ${error}`
			);
		}
	}

	console.log(
		`[DEBUG] Script completed. Processed ${processedCount} issues, found ${candidateCount} candidates for auto-close`
	);
}

autoCloseDuplicates().catch(console.error);
