/**
 * Auto-updater module for Maestro
 * Uses electron-updater to download and install updates from GitHub releases
 *
 * Note: electron-updater accesses electron.app at module load time, so we use
 * lazy initialization to avoid "Cannot read properties of undefined" errors
 * when the module is imported before app.whenReady().
 */

import type { UpdateInfo, ProgressInfo, AppUpdater } from 'electron-updater';
import { BrowserWindow, ipcMain } from 'electron';
import { logger } from './utils/logger';
import { isWebContentsAvailable } from './utils/safe-send';

export interface UpdateStatus {
	status:
		| 'idle'
		| 'checking'
		| 'available'
		| 'not-available'
		| 'downloading'
		| 'downloaded'
		| 'error';
	info?: UpdateInfo;
	progress?: ProgressInfo;
	error?: string;
}

let mainWindow: BrowserWindow | null = null;
let currentStatus: UpdateStatus = { status: 'idle' };
let ipcHandlersRegistered = false;

// Lazy-loaded autoUpdater instance
let _autoUpdater: AppUpdater | null = null;

/**
 * Get the autoUpdater instance, initializing it lazily
 * This is necessary because electron-updater accesses electron.app at import time
 */
function getAutoUpdater(): AppUpdater {
	if (!_autoUpdater) {
		// Dynamic require to defer the module load
		const { autoUpdater } = require('electron-updater');
		_autoUpdater = autoUpdater;
		// Configure defaults
		_autoUpdater!.autoDownload = false;
		_autoUpdater!.autoInstallOnAppQuit = true;
		_autoUpdater!.allowPrerelease = false;
	}
	return _autoUpdater!;
}

/**
 * Initialize the auto-updater and set up event handlers
 */
export function initAutoUpdater(window: BrowserWindow): void {
	mainWindow = window;

	const autoUpdater = getAutoUpdater();

	// Update available
	autoUpdater.on('update-available', (info: UpdateInfo) => {
		logger.info(`Update available: ${info.version}`, 'AutoUpdater');
		currentStatus = { status: 'available', info };
		sendStatusToRenderer();
	});

	// No update available
	autoUpdater.on('update-not-available', (info: UpdateInfo) => {
		logger.debug(`No update available (current: ${info.version})`, 'AutoUpdater');
		currentStatus = { status: 'not-available', info };
		sendStatusToRenderer();
	});

	// Download progress
	autoUpdater.on('download-progress', (progress: ProgressInfo) => {
		currentStatus = { ...currentStatus, status: 'downloading', progress };
		sendStatusToRenderer();
	});

	// Update downloaded
	autoUpdater.on('update-downloaded', (info: UpdateInfo) => {
		logger.info(`Update downloaded: ${info.version}`, 'AutoUpdater');
		currentStatus = { status: 'downloaded', info };
		sendStatusToRenderer();
	});

	// Error
	autoUpdater.on('error', (err: Error) => {
		logger.error(`Auto-update error: ${err.message}`, 'AutoUpdater');
		currentStatus = { status: 'error', error: err.message };
		sendStatusToRenderer();
	});

	// Set up IPC handlers
	setupIpcHandlers();
}

/**
 * Send current status to renderer
 */
function sendStatusToRenderer(): void {
	if (isWebContentsAvailable(mainWindow)) {
		mainWindow.webContents.send('updates:status', currentStatus);
	}
}

/**
 * Set up IPC handlers for update operations
 */
function setupIpcHandlers(): void {
	if (ipcHandlersRegistered) {
		return;
	}
	ipcHandlersRegistered = true;

	const autoUpdater = getAutoUpdater();

	// Check for updates using electron-updater (different from manual GitHub API check)
	ipcMain.handle('updates:checkAutoUpdater', async () => {
		try {
			currentStatus = { status: 'checking' };
			sendStatusToRenderer();
			const result = await autoUpdater.checkForUpdates();
			return { success: true, updateInfo: result?.updateInfo };
		} catch (error) {
			const errorMessage = error instanceof Error ? error.message : 'Unknown error';
			currentStatus = { status: 'error', error: errorMessage };
			sendStatusToRenderer();
			return { success: false, error: errorMessage };
		}
	});

	// Download update
	ipcMain.handle('updates:download', async () => {
		try {
			// First, check for updates with electron-updater to tell it which version to download
			// This is required because the UI uses the GitHub API check, not electron-updater's check
			logger.info('Checking for updates before download...', 'AutoUpdater');
			const checkResult = await autoUpdater.checkForUpdates();

			if (!checkResult || !checkResult.updateInfo) {
				logger.error('No update found during pre-download check', 'AutoUpdater');
				currentStatus = { status: 'error', error: 'No update available to download' };
				sendStatusToRenderer();
				return { success: false, error: 'No update available to download' };
			}

			logger.info(
				`Found update ${checkResult.updateInfo.version}, starting download...`,
				'AutoUpdater'
			);
			currentStatus = {
				status: 'downloading',
				progress: { percent: 0, bytesPerSecond: 0, total: 0, transferred: 0, delta: 0 },
			};
			sendStatusToRenderer();
			await autoUpdater.downloadUpdate();
			return { success: true };
		} catch (error) {
			const errorMessage = error instanceof Error ? error.message : 'Unknown error';
			logger.error(`Download failed: ${errorMessage}`, 'AutoUpdater');
			currentStatus = { status: 'error', error: errorMessage };
			sendStatusToRenderer();
			return { success: false, error: errorMessage };
		}
	});

	// Install update (quit and install)
	ipcMain.handle('updates:install', () => {
		autoUpdater.quitAndInstall(false, true);
	});

	// Get current status
	ipcMain.handle('updates:getStatus', () => {
		return currentStatus;
	});
}

/**
 * Manually trigger update check (can be called from main process)
 */
export async function checkForUpdatesManual(): Promise<UpdateInfo | null> {
	try {
		const autoUpdater = getAutoUpdater();
		const result = await autoUpdater.checkForUpdates();
		return result?.updateInfo || null;
	} catch {
		return null;
	}
}

/**
 * Configure whether to include prerelease/beta versions in updates
 * This should be called when the user setting changes
 */
export function setAllowPrerelease(allow: boolean): void {
	const autoUpdater = getAutoUpdater();
	autoUpdater.allowPrerelease = allow;
	logger.info(`Auto-updater prerelease mode: ${allow ? 'enabled' : 'disabled'}`, 'AutoUpdater');
}
