const { prisma } = require("./shared/prisma");
const { compareVersions, checkPublicRepo } = require("./shared/utils");

/**
 * GitHub Update Check Automation
 * Checks for new releases on GitHub using HTTPS API
 */
class GitHubUpdateCheck {
	constructor(queueManager) {
		this.queueManager = queueManager;
		this.queueName = "github-update-check";
	}

	/**
	 * Process GitHub update check job
	 */
	async process(_job) {
		const startTime = Date.now();
		console.log("🔍 Starting GitHub update check...");

		try {
			// Get settings
			const settings = await prisma.settings.findFirst();
			const DEFAULT_GITHUB_REPO = "https://github.com/PatchMon/PatchMon.git";
			const repoUrl = settings?.githubRepoUrl || DEFAULT_GITHUB_REPO;
			let owner, repo;

			// Parse GitHub repository URL (supports both HTTPS and SSH formats)
			if (repoUrl.includes("git@github.com:")) {
				const match = repoUrl.match(/git@github\.com:([^/]+)\/([^/]+)\.git/);
				if (match) {
					[, owner, repo] = match;
				}
			} else if (repoUrl.includes("github.com/")) {
				const match = repoUrl.match(
					/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/,
				);
				if (match) {
					[, owner, repo] = match;
				}
			}

			if (!owner || !repo) {
				throw new Error("Could not parse GitHub repository URL");
			}

			// Always use HTTPS GitHub API (simpler and more reliable)
			const latestVersion = await checkPublicRepo(owner, repo);

			if (!latestVersion) {
				throw new Error("Could not determine latest version");
			}

			// Read version from package.json
			let currentVersion = null;
			try {
				const packageJson = require("../../../package.json");
				if (packageJson?.version) {
					currentVersion = packageJson.version;
				}
			} catch (packageError) {
				console.error(
					"Could not read version from package.json:",
					packageError.message,
				);
				throw new Error(
					"Could not determine current version from package.json",
				);
			}

			if (!currentVersion) {
				throw new Error("Version not found in package.json");
			}

			const isUpdateAvailable =
				compareVersions(latestVersion, currentVersion) > 0;

			// Update settings with check results
			await prisma.settings.update({
				where: { id: settings.id },
				data: {
					last_update_check: new Date(),
					update_available: isUpdateAvailable,
					latest_version: latestVersion,
				},
			});

			const executionTime = Date.now() - startTime;
			console.log(
				`✅ GitHub update check completed in ${executionTime}ms - Current: ${currentVersion}, Latest: ${latestVersion}, Update Available: ${isUpdateAvailable}`,
			);

			return {
				success: true,
				currentVersion,
				latestVersion,
				isUpdateAvailable,
				executionTime,
			};
		} catch (error) {
			const executionTime = Date.now() - startTime;
			console.error(
				`❌ GitHub update check failed after ${executionTime}ms:`,
				error.message,
			);

			// Update last check time even on error
			try {
				const settings = await prisma.settings.findFirst();
				if (settings) {
					await prisma.settings.update({
						where: { id: settings.id },
						data: {
							last_update_check: new Date(),
							update_available: false,
						},
					});
				}
			} catch (updateError) {
				console.error(
					"❌ Error updating last check time:",
					updateError.message,
				);
			}

			throw error;
		}
	}

	/**
	 * Schedule recurring GitHub update check (daily at midnight)
	 */
	async schedule() {
		const job = await this.queueManager.queues[this.queueName].add(
			"github-update-check",
			{},
			{
				repeat: { cron: "0 0 * * *" }, // Daily at midnight
				jobId: "github-update-check-recurring",
			},
		);
		console.log("✅ GitHub update check scheduled");
		return job;
	}

	/**
	 * Trigger manual GitHub update check
	 */
	async triggerManual() {
		const job = await this.queueManager.queues[this.queueName].add(
			"github-update-check-manual",
			{},
			{ priority: 1 },
		);
		console.log("✅ Manual GitHub update check triggered");
		return job;
	}
}

module.exports = GitHubUpdateCheck;
