/**
 * Electron IPC main process registry.
 *
 * Centralizes all IPC channels exposed to renderer process:
 * - Application info (version, features)
 * - Window controls (topbar actions)
 * - File system interactions (theme, config, download paths)
 * - UI state synchronization (progress bar)
 *
 * Acts as the bridge between renderer and privileged Node/Electron APIs.
 */

const { ipcMain, dialog, shell } = require("electron");
const fs = require("fs");
const path = require("path");
const { logger, logDir } = require("../server/logger");
const { configFeatures, featuresPath } = require("../config");
const { getThemes, reloadThemes } = require("./themeManager");
const config = require("../config");
const { validateDownloadPath, getDefaultDownloadPath } = require("./pathValidator");
const { userThemesPath } = require("../server/helpers/path.helpers");

/**
 * Security whitelist for feature flags that can be modified at runtime.
 *
 * Prevents unauthorized or unexpected configuration keys from being persisted.
 * Acts as a basic validation layer for IPC "set-feature".
 */
const FEATURE_WHITELIST = new Set([
  "autoUpdate",
  "discordRPC",
  "customTopBar",
  "autoCheckInfo",
  "addThumbnail",
  "addMetadata",
  "verboseLogs",
  "autoDownloadPlaylist",
  "customCodec",
  "theme",
  "createPlaylistFolders",
  "notifySystem",
  "enableHardwareAcceleration"
]);

/**
 * Absolute path to the configuration file storing feature flags.
 */
const configFolderPath = featuresPath;

/**
 * Directory containing user-installed themes.
 */
const themeFolderPath = userThemesPath;

/**
 * Registers all IPC handlers and event listeners for Electron main process.
 *
 * This function wires renderer → main communication channels:
 * - synchronous queries (handle)
 * - fire-and-forget events (on)
 *
 * @param {Function} getMainWindow - Function returning current BrowserWindow instance
 */
function registerIpcHandlers(getMainWindow) {
    
  /**
   * Returns application version from config.
   */
  ipcMain.handle("version", () => config.version);

  /**
   * Returns runtime feature configuration object.
   */
  ipcMain.handle("features", () => configFeatures);

  /**
   * Opens native folder selection dialog and validates selected path.
   *
   * Ensures:
   * - user cancellation is handled safely
   * - selected path is validated against security rules
   * - unsafe directories are rejected
   */
  ipcMain.handle("select-download-folder", async () => {
    const result = await dialog.showOpenDialog({ properties: ["openDirectory"] });
    if (result.canceled) {
      logger.info("Folder selection cancelled by user");
      return null;
    }
    try {
      const validated = validateDownloadPath(result.filePaths[0]);
      logger.info(`Folder selected and validated: ${validated}`);
      return validated;
    } catch (err) {
      logger.warn(`Unsafe or invalid folder rejected: ${err.message}`);
      throw err;
    }
  });

  ipcMain.handle("validate-download-path", (_, userPath) => validateDownloadPath(userPath));
  ipcMain.handle("get-default-download-path", () => getDefaultDownloadPath());

  /**
   * Updates Windows/macOS taskbar progress indicator.
   *
   * @param {number} percent - Progress value (0–100)
   */
  ipcMain.on("set-progress", (_, percent) => {
    getMainWindow()?.setProgressBar(percent / 100);
  });

  /**
   * Window minimize request from renderer.
   */
  ipcMain.on("window-minimize", () => getMainWindow()?.minimize());

  /**
   * Toggles maximize/unmaximize state of main window.
   */
  ipcMain.on("window-maximize", () => {
    const win = getMainWindow();
    if (!win) return;
    win.isMaximized() ? win.unmaximize() : win.maximize();
  });

  /**
   * Closes the main application window.
   */
  ipcMain.on("window-close", () => getMainWindow()?.close());


  /**
   * Opens Chromium DevTools in detached mode.
   */
  ipcMain.on("open-devtools", () =>
    getMainWindow()?.webContents.openDevTools({ mode: "detach" })
  );

  /**
   * Opens application logs directory in system file explorer.
   */
  ipcMain.on("open-logs",    () => logDir && shell.openPath(logDir));

  /**
   * Opens external website in default browser.
   */
  ipcMain.on("open-website", () =>
    shell.openExternal("https://masteracnolo.github.io/Freedom-Loader-Site/")
  );

  /**
   * Opens official wiki page in external browser.
   */
  ipcMain.on("open-wiki", () =>
    shell.openExternal("https://masteracnolo.github.io/Freedom-Loader-Site/wiki")
  );

  /**
   * Opens workshop page in external browser.
   */
  ipcMain.on("open-workshop", () =>
    shell.openExternal("https://masteracnolo.github.io/Freedom-Loader-Workshop")
  );

  /**
   * Opens configuration folder in system file explorer.
   */
  ipcMain.on("open-config", () => shell.openPath(configFolderPath));

  
  
  /**
   * Retrieves available themes from filesystem.
   */
  ipcMain.handle("get-themes", () => getThemes());

  /**
   * Opens theme directory in file explorer.
   */
  ipcMain.on("open-theme", () => shell.openPath(themeFolderPath));

  /**
   * Reloads themes from disk dynamically.
   */
  ipcMain.handle("reload-themes", async () => {
    return await reloadThemes();
  });

  /**
   * Updates a runtime feature flag and persists it to disk.
   *
   * Flow:
   * - Validates key against whitelist
   * - Prevents unnecessary writes if value is unchanged
   * - Updates in-memory config object
   * - Persists to configuration file
   *
   * Security note:
   * Only whitelisted keys can be modified via IPC to prevent config injection.
   *
   * @param {Electron.IpcMainEvent} event
   * @param {{key: string, value: any}} payload
   * @returns {boolean} success state
   */
  ipcMain.handle("set-feature", (event, { key, value }) => {
        try {
          if (!FEATURE_WHITELIST.has(key)) {
            logger.warn(`Rejected feature (not whitelisted): ${key}`);
            return false;
          }

          if (configFeatures[key] === value) {
            return true;
          }

          configFeatures[key] = value;

          fs.writeFileSync(
            configFolderPath,
            JSON.stringify(configFeatures, null, 2),
            "utf-8"
          );

          logger.info(`Feature updated: ${key} = ${value}`);
          return true;

        } catch (err) {
          logger.error(`set-feature failed (${key}): ${err.message}`);
          return false;
        }
    });
}

module.exports = { registerIpcHandlers };