const { app, BrowserWindow, Menu, dialog, ipcMain, shell } = require('electron');
const path = require('path');
const fs = require('fs');
const { exec, execFile, spawn } = require('child_process');
const WordTemplateExporter = require('./wordTemplateExporter');
const PDFOperations = require('./main/PDFOperations');
const GitOperations = require('./main/GitOperations');

// Add MiKTeX to PATH for LaTeX support
if (process.platform === 'win32') {
  const miktexPath = 'C:\\Program Files\\MiKTeX\\miktex\\bin\\x64';
  if (fs.existsSync(miktexPath)) {
    process.env.PATH = `${miktexPath};${process.env.PATH}`;
    console.log('[MAIN] Added MiKTeX to PATH:', miktexPath);
  }
}

// Returns path to pandoc: bundled binary when packaged, dev bin or system fallback otherwise.
function getPandocPath() {
  if (app.isPackaged) {
    const ext = process.platform === 'win32' ? '.exe' : '';
    return path.join(process.resourcesPath, 'bin', `pandoc${ext}`);
  }
  // Development: prefer locally-downloaded binary in bin/<platform>/
  const devBin = path.join(
    __dirname,
    '..',
    'bin',
    process.platform,
    process.platform === 'win32' ? 'pandoc.exe' : 'pandoc',
  );
  if (fs.existsSync(devBin)) return devBin;
  return 'pandoc';
}

// Returns path to ffmpeg: asar-unpacked bundled binary when packaged, system fallback otherwise.
function getFFmpegPath() {
  try {
    let ffmpegPath = require('ffmpeg-static');
    if (app.isPackaged) {
      // ffmpeg-static is in asarUnpack — rewrite the path to the unpacked location
      ffmpegPath = ffmpegPath.replace('app.asar' + path.sep, 'app.asar.unpacked' + path.sep);
    }
    if (fs.existsSync(ffmpegPath)) return ffmpegPath;
  } catch (_) {
    /* ffmpeg-static not available */
  }
  return process.platform === 'win32' ? 'ffmpeg' : 'ffmpeg';
}

// Check if Pandoc is available
function checkPandocAvailable() {
  return new Promise((resolve) => {
    const pandocPath = getPandocPath();
    execFile(pandocPath, ['--version'], (error) => {
      resolve(!error);
    });
  });
}

/**
 * Safe command execution using execFile (no shell injection risk)
 * @param {string} command - The command to execute
 * @param {string[]} args - Array of arguments
 * @param {object} options - Options for execFile
 * @returns {Promise<{stdout: string, stderr: string}>}
 */
function safeExecFile(command, args, options = {}) {
  return new Promise((resolve, reject) => {
    execFile(command, args, { maxBuffer: 10 * 1024 * 1024, ...options }, (error, stdout, stderr) => {
      if (error) {
        reject({ error, stdout, stderr });
      } else {
        resolve({ stdout, stderr });
      }
    });
  });
}

// File size validation
const MAX_FILE_SIZE_MB = 50;
const MAX_FILE_SIZE = MAX_FILE_SIZE_MB * 1024 * 1024;

// Sanitize error messages to strip absolute file paths
function sanitizeErrorMessage(message) {
    if (typeof message !== 'string') return String(message);
    // Strip absolute Windows paths, keeping only filename
    return message
        .replace(/[A-Z]:\\[^\s"']+\\([^\s"'\\]+)/gi, '$1')
        .replace(/\/[^\s"']+\/([^\s"'/]+)/g, '$1');
}

// Rate limiter for conversions
function createRateLimiter(minIntervalMs = 2000) {
    let lastCall = 0;
    return function canProceed() {
        const now = Date.now();
        if (now - lastCall < minIntervalMs) return false;
        lastCall = now;
        return true;
    };
}
const conversionLimiter = createRateLimiter(2000);

// ============================================
// Path Traversal Protection
// ============================================
// Define allowed base directories for file operations
function getAllowedDirectories() {
  const dirs = [
    app.getPath('documents'),
    app.getPath('desktop'),
    app.getPath('downloads'),
    app.getPath('home'),
    process.cwd() // Current working directory
  ].filter(Boolean); // Remove any undefined paths
  return dirs;
}

/**
 * Validates that a file path is safe and doesn't attempt path traversal
 * @param {string} filePath - The path to validate
 * @returns {{ valid: boolean, resolved: string, error?: string }}
 */
function validatePath(filePath) {
  if (!filePath || typeof filePath !== 'string') {
    return { valid: false, resolved: '', error: 'Invalid path' };
  }

  // Resolve to absolute path (handles .., ., symlinks)
  let resolved;
  try {
    resolved = path.resolve(filePath);
  } catch (err) {
    return { valid: false, resolved: '', error: 'Invalid path format' };
  }

  // Normalize path separators
  resolved = path.normalize(resolved);

  // Check for null bytes (path injection)
  if (resolved.includes('\0')) {
    return { valid: false, resolved: '', error: 'Null byte in path' };
  }

  // Check if path exists
  if (!fs.existsSync(resolved)) {
    return { valid: false, resolved, error: 'Path does not exist' };
  }

  return { valid: true, resolved };
}

/**
 * Resolves a path for operations where the target may not exist yet.
 * Validates string shape and blocks obviously sensitive locations.
 * @param {string} filePath
 * @returns {{ valid: boolean, resolved: string, error?: string }}
 */
function resolveWritablePath(filePath) {
  if (!filePath || typeof filePath !== 'string') {
    return { valid: false, resolved: '', error: 'Invalid path' };
  }

  let resolved;
  try {
    resolved = path.normalize(path.resolve(filePath));
  } catch (err) {
    return { valid: false, resolved: '', error: 'Invalid path format' };
  }

  if (resolved.includes('\0')) {
    return { valid: false, resolved: '', error: 'Null byte in path' };
  }

  if (!isPathAccessible(resolved)) {
    return { valid: false, resolved, error: 'Path is not accessible' };
  }

  return { valid: true, resolved };
}

/**
 * Checks if a resolved path is within allowed directories
 * For an editor app, we allow access to all user-accessible paths
 * but log any suspicious access attempts
 * @param {string} resolvedPath - The resolved absolute path
 * @returns {boolean}
 */
function isPathAccessible(resolvedPath) {
  // Block access to sensitive system directories
  const blockedPaths = [
    '/etc/passwd', '/etc/shadow', '/root',
    'C:\\Windows\\System32', 'C:\\Windows\\System',
    '/System', '/private/etc'
  ];

  const normalizedPath = resolvedPath.toLowerCase();
  for (const blocked of blockedPaths) {
    if (normalizedPath.startsWith(blocked.toLowerCase())) {
      console.warn('[SECURITY] Blocked access to sensitive path:', resolvedPath);
      return false;
    }
  }

  return true;
}

// Convert structured data formats to markdown code blocks
function convertDataToMarkdown(content, format) {
    switch (format) {
        case 'json':
            return '```json\n' + content + '\n```';
        case 'yaml':
        case 'yml':
            return '```yaml\n' + content + '\n```';
        case 'xml':
            return '```xml\n' + content + '\n```';
        case 'toml':
            return '```toml\n' + content + '\n```';
        default:
            return '```\n' + content + '\n```';
    }
}

/**
 * Run Pandoc command safely with execFile
 * @param {string[]} args - Pandoc arguments array
 * @param {Function} callback - Callback function (error, stdout, stderr)
 */
function runPandoc(args, callback) {
  const pandocPath = getPandocPath();
  execFile(pandocPath, args, { maxBuffer: 10 * 1024 * 1024 }, callback);
}

/**
 * Run a Pandoc command string safely using execFile
 * Parses the command string and uses execFile to prevent shell injection
 * @param {string} cmdString - Full Pandoc command string (e.g., 'pandoc "input.md" -o "output.pdf"')
 * @param {Function} callback - Callback function (error, stdout, stderr)
 */
function runPandocCmd(cmdString, callback) {
  const parsed = parseCommand(cmdString);
  // Skip 'pandoc' if it's the first element (command itself)
  // Use path.basename to handle full paths like bin/linux/pandoc
  const cmdBase = path.basename(parsed.command).replace(/\.exe$/i, '');
  const args = cmdBase === 'pandoc' ? parsed.args : [parsed.command, ...parsed.args];
  const pandocPath = getPandocPath();
  execFile(pandocPath, args, { maxBuffer: 10 * 1024 * 1024 }, callback);
}

/**
 * Parse a command string into command and arguments array
 * This helps transition from exec() to execFile() safely
 * @param {string} cmdString - Full command string
 * @returns {{command: string, args: string[]}}
 */
function parseCommand(cmdString) {
  // Handle quoted strings properly
  const parts = [];
  let current = '';
  let inQuotes = false;
  let quoteChar = '';

  for (let i = 0; i < cmdString.length; i++) {
    const char = cmdString[i];
    if ((char === '"' || char === "'") && !inQuotes) {
      inQuotes = true;
      quoteChar = char;
    } else if (char === quoteChar && inQuotes) {
      inQuotes = false;
      quoteChar = '';
    } else if (char === ' ' && !inQuotes) {
      if (current) {
        parts.push(current);
        current = '';
      }
    } else {
      current += char;
    }
  }
  if (current) {
    parts.push(current);
  }

  return {
    command: parts[0],
    args: parts.slice(1)
  };
}

// Simple storage implementation to replace electron-store
const settingsPath = path.join(app.getPath('userData'), 'settings.json');
const store = {
  get: (key, defaultValue) => {
    try {
      const data = fs.readFileSync(settingsPath, 'utf-8');
      const settings = JSON.parse(data);
      return settings[key] || defaultValue;
    } catch {
      return defaultValue;
    }
  },
  set: (key, value) => {
    let settings = {};
    try {
      const data = fs.readFileSync(settingsPath, 'utf-8');
      settings = JSON.parse(data);
    } catch {}
    settings[key] = value;
    fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
  }
};

// Plugin settings IPC handlers
ipcMain.handle('plugin-settings:get', (_event, key) => {
  return store.get(key);
});
ipcMain.handle('plugin-settings:set', (_event, { key, value }) => {
  store.set(key, value);
});
ipcMain.handle('get-app-version', () => app.getVersion());

// ============================================
// SECURITY: Permission Request Handler
// ============================================
// Restrict permissions to only those explicitly needed.
// Deny: camera, microphone, geolocation, notifications, etc.
// Allow: clipboard-read, clipboard-write (user expects these)
app.on('web-contents-created', (event, contents) => {
  contents.session.setPermissionRequestHandler((webContents, permission, callback) => {
    const ALLOWED_PERMISSIONS = [
      'clipboard-read',
      'clipboard-write'
    ];

    if (ALLOWED_PERMISSIONS.includes(permission)) {
      callback(true);
    } else {
      // Deny all other permissions (camera, microphone, geolocation, etc.)
      console.warn(`[Security] Blocked permission request: ${permission}`);
      callback(false);
    }
  });

  // Disable file download dialogs for security
  // contents.session.setDownloadPath(userDownloadsPath);
});

let mainWindow;
let currentFile = null; // This will now represent the active tab's file
let pandocAvailable = null; // Cache pandoc availability check
let wordTemplatePath = null; // Path to selected Word template
let templateStartPage = 3; // Which page to start inserting content (default: page 3)
let rendererReady = false; // Track if renderer is ready to receive file data

// Header & Footer Settings
let headerFooterSettings = {
  enabled: true,
  header: {
    left: '',
    center: '',
    right: '',
    logo: null // Will store image file path
  },
  footer: {
    left: '',
    center: '$PAGE$ of $TOTAL$',
    right: '',
    logo: null
  }
};

// Page Size Definitions (in twentieths of a point for Word, mm/inches for Pandoc)
const PAGE_SIZES = {
  a4: {
    name: 'A4',
    pandoc: 'a4',
    word: { width: 11906, height: 16838 }, // 210×297mm
    dimensions: '210×297mm'
  },
  a3: {
    name: 'A3',
    pandoc: 'a3',
    word: { width: 16838, height: 23811 }, // 297×420mm
    dimensions: '297×420mm'
  },
  a5: {
    name: 'A5',
    pandoc: 'a5',
    word: { width: 8391, height: 11906 }, // 148×210mm
    dimensions: '148×210mm'
  },
  b4: {
    name: 'B4',
    pandoc: 'b4',
    word: { width: 14170, height: 20015 }, // 250×353mm
    dimensions: '250×353mm'
  },
  b5: {
    name: 'B5',
    pandoc: 'b5',
    word: { width: 9979, height: 14170 }, // 176×250mm
    dimensions: '176×250mm'
  },
  letter: {
    name: 'Letter',
    pandoc: 'letter',
    word: { width: 12240, height: 15840 }, // 8.5×11in
    dimensions: '8.5×11in'
  },
  legal: {
    name: 'Legal',
    pandoc: 'legal',
    word: { width: 12240, height: 20160 }, // 8.5×14in
    dimensions: '8.5×14in'
  },
  tabloid: {
    name: 'Tabloid',
    pandoc: 'tabloid',
    word: { width: 15840, height: 24480 }, // 11×17in
    dimensions: '11×17in'
  }
};

// Default page settings
let pageSettings = {
  size: 'a4',
  orientation: 'portrait',
  customWidth: null,
  customHeight: null
};

// Handle single instance lock for Windows file association
// When a file is double-clicked and the app is already running,
// Windows tries to start a second instance. We prevent this and
// pass the file to the existing instance instead.
const gotTheLock = app.requestSingleInstanceLock();

if (!gotTheLock) {
  // Another instance is already running, quit this one
  app.quit();
} else {
  // This is the first instance, handle second-instance events
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // Someone tried to run a second instance, focus our window instead
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore();
      mainWindow.focus();
    }

    // Check if a file was passed to the second instance
    // commandLine is an array like: ['PanConverter.exe', 'file.md']
    console.log('[MAIN] Second instance commandLine:', JSON.stringify(commandLine));
    const startIndex = app.isPackaged ? 1 : 2;
    const fileArgs = commandLine.slice(startIndex);
    console.log('[MAIN] Second instance file args:', fileArgs);
    for (const arg of fileArgs) {
      if ((arg.endsWith('.md') || arg.endsWith('.markdown'))) {
        const resolvedPath = path.isAbsolute(arg) ? arg : path.resolve(workingDirectory, arg);
        console.log('[MAIN] Second instance resolved path:', resolvedPath);
        if (fs.existsSync(resolvedPath)) {
          // Open the file in the existing instance
          if (rendererReady) {
            openFileFromPath(resolvedPath);
          } else {
            app.pendingFile = resolvedPath;
          }
          break;
        }
      }
    }
  });
}

// Check if pandoc is available (using execFile for consistency)
function checkPandocAvailability() {
  return new Promise((resolve) => {
    if (pandocAvailable !== null) {
      resolve(pandocAvailable);
      return;
    }

    execFile('pandoc', ['--version'], (error, stdout, stderr) => {
      pandocAvailable = !error;
      resolve(pandocAvailable);
    });
  });
}

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    show: false,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      spellcheck: true
    },
    icon: path.join(__dirname, '../assets/icon.png')
  });

  mainWindow.loadFile(path.join(__dirname, 'index.html'));

  // Show window only after content is ready — avoids blank flash
  mainWindow.once('ready-to-show', () => {
    mainWindow.show();
  });

  createMenu();

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  // Spell check context menu
  mainWindow.webContents.on('context-menu', (event, params) => {
    const { Menu, MenuItem } = require('electron');
    const menu = new Menu();

    // Add spell check suggestions
    if (params.misspelledWord) {
      for (const suggestion of params.dictionarySuggestions) {
        menu.append(new MenuItem({
          label: suggestion,
          click: () => mainWindow.webContents.replaceMisspelling(suggestion)
        }));
      }
      if (params.dictionarySuggestions.length > 0) {
        menu.append(new MenuItem({ type: 'separator' }));
      }
      menu.append(new MenuItem({
        label: 'Add to Dictionary',
        click: () => mainWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
      }));
      menu.append(new MenuItem({ type: 'separator' }));
    }

    // Standard context menu items
    menu.append(new MenuItem({ role: 'cut' }));
    menu.append(new MenuItem({ role: 'copy' }));
    menu.append(new MenuItem({ role: 'paste' }));
    menu.append(new MenuItem({ role: 'selectAll' }));

    menu.popup();
  });

  // Wait for the page to fully load before sending file data
  mainWindow.webContents.on('did-finish-load', () => {
    console.log('Window finished loading');
    // Don't open file here - wait for renderer-ready signal
    // The renderer will send renderer-ready when TabManager is initialized
  });
}

function buildRecentFilesMenu() {
  const recentFiles = getRecentFiles();

  if (recentFiles.length === 0) {
    return [
      {
        label: 'No recent files',
        enabled: false
      }
    ];
  }

  const recentFileItems = recentFiles.map(filePath => ({
    label: filePath.split(/[\\/]/).pop(), // Get filename only
    click: () => {
      if (fs.existsSync(filePath)) {
        const stats = fs.statSync(filePath);
        if (stats.size > MAX_FILE_SIZE) {
            dialog.showErrorBox('File Too Large', `File exceeds the ${MAX_FILE_SIZE_MB}MB size limit.`);
            return;
        }
        currentFile = filePath;
        const content = fs.readFileSync(filePath, 'utf-8');
        mainWindow.webContents.send('file-opened', { path: filePath, content });
      } else {
        dialog.showErrorBox('File Not Found', sanitizeErrorMessage(`The file "${filePath}" could not be found.`));
      }
    },
    toolTip: filePath // Show full path in tooltip
  }));

  return [
    ...recentFileItems,
    { type: 'separator' },
    {
      label: 'Clear Recent Files',
      click: () => {
        mainWindow.webContents.send('clear-recent-files');
      }
    }
  ];
}

function getRecentFiles() {
  try {
    const recentFiles = JSON.parse(fs.readFileSync(path.join(app.getPath('userData'), 'recent-files.json'), 'utf-8'));
    return recentFiles.filter(file => fs.existsSync(file));
  } catch (e) {
    return [];
  }
}

function createMenu() {
  const template = [
    {
      label: 'File',
      submenu: [
        {
          label: 'New',
          accelerator: 'CmdOrCtrl+N',
          click: () => mainWindow.webContents.send('file-new')
        },
        {
          label: 'Open',
          accelerator: 'CmdOrCtrl+O',
          click: openFile
        },
        {
          label: 'Open PDF',
          accelerator: 'CmdOrCtrl+Shift+O',
          click: openPdfFile
        },
        {
          label: 'Save',
          accelerator: 'CmdOrCtrl+S',
          click: () => mainWindow.webContents.send('file-save')
        },
        {
          label: 'Save As',
          accelerator: 'CmdOrCtrl+Shift+S',
          click: saveAsFile
        },
        { type: 'separator' },
        {
          label: 'Print',
          submenu: [
            {
              label: 'Print Preview',
              accelerator: 'CmdOrCtrl+P',
              click: () => mainWindow.webContents.send('print-preview')
            },
            {
              label: 'Print Preview (With Styles)',
              click: () => mainWindow.webContents.send('print-preview-styled')
            }
          ]
        },
        { type: 'separator' },
        {
          label: 'Recent Files',
          submenu: buildRecentFilesMenu()
        },
        { type: 'separator' },
        {
          label: 'New from Template',
          submenu: [
            { label: 'Blog Post', click: () => mainWindow.webContents.send('load-template-menu', 'blog-post.md') },
            { label: 'Meeting Notes', click: () => mainWindow.webContents.send('load-template-menu', 'meeting-notes.md') },
            { label: 'Technical Spec', click: () => mainWindow.webContents.send('load-template-menu', 'technical-spec.md') },
            { label: 'Changelog', click: () => mainWindow.webContents.send('load-template-menu', 'changelog.md') },
            { label: 'README', click: () => mainWindow.webContents.send('load-template-menu', 'readme.md') },
            { label: 'Project Plan', click: () => mainWindow.webContents.send('load-template-menu', 'project-plan.md') },
            { label: 'API Documentation', click: () => mainWindow.webContents.send('load-template-menu', 'api-docs.md') },
            { label: 'Tutorial', click: () => mainWindow.webContents.send('load-template-menu', 'tutorial.md') },
            { label: 'Release Notes', click: () => mainWindow.webContents.send('load-template-menu', 'release-notes.md') },
            { label: 'Comparison', click: () => mainWindow.webContents.send('load-template-menu', 'comparison.md') }
          ]
        },
        { type: 'separator' },
        {
          label: 'Import Document...',
          accelerator: 'CmdOrCtrl+I',
          click: importDocument
        },
        {
          label: 'Export',
          submenu: [
            { label: 'HTML', click: () => exportFile('html') },
            { label: 'PDF', click: () => exportFile('pdf') },
            { label: 'PDF (Enhanced)', click: () => exportPDFViaWordTemplate(), accelerator: 'Ctrl+Shift+P' },
            { label: 'DOCX', click: () => exportFile('docx') },
            { label: 'DOCX (Enhanced)', click: () => exportWordWithTemplate(), accelerator: 'Ctrl+Shift+W' },
            { label: 'LaTeX', click: () => exportFile('latex') },
            { label: 'RTF', click: () => exportFile('rtf') },
            { label: 'ODT', click: () => exportFile('odt') },
            { label: 'EPUB', click: () => exportFile('epub') },
            { type: 'separator' },
            { label: 'PowerPoint (PPTX)', click: () => exportFile('pptx') },
            { label: 'OpenDocument Presentation (ODP)', click: () => exportFile('odp') },
            { type: 'separator' },
            { label: 'CSV (Tables)', click: () => exportSpreadsheet('csv') },
            { type: 'separator' },
            { label: 'JSON (.json)', click: () => exportFile('json') },
            { label: 'YAML (.yaml)', click: () => exportFile('yaml') },
            { label: 'XML (.xml)', click: () => exportFile('xml') },
            { label: 'TOML (.toml)', click: () => exportFile('toml') },
            { type: 'separator' },
            { label: 'Reveal.js Slides (.html)', click: () => exportFile('revealjs') },
            { label: 'Beamer Slides (.pdf)', click: () => exportFile('beamer') },
            { type: 'separator' },
            { label: 'Confluence Wiki (.txt)', click: () => exportFile('confluence') },
            { label: 'MOBI E-book (.mobi)', click: () => exportFile('mobi') },
          ]
        },
        { type: 'separator' },
        {
          label: 'Select Word Template...',
          click: selectWordTemplate
        },
        {
          label: 'Template Settings...',
          click: showTemplateSettings
        },
        {
          label: 'Header & Footer Settings...',
          click: () => {
            if (mainWindow) {
              mainWindow.webContents.send('open-header-footer-dialog');
            }
          }
        },
        { type: 'separator' },
        {
          label: 'Quit',
          accelerator: process.platform === 'darwin' ? 'Cmd+Q' : 'Ctrl+Q',
          click: () => app.quit()
        }
      ]
    },
    {
      label: 'Edit',
      submenu: [
        {
          label: 'Undo',
          accelerator: 'CmdOrCtrl+Z',
          click: () => mainWindow.webContents.send('undo')
        },
        {
          label: 'Redo',
          accelerator: 'CmdOrCtrl+Shift+Z',
          click: () => mainWindow.webContents.send('redo')
        },
        { type: 'separator' },
        { label: 'Cut', accelerator: 'CmdOrCtrl+X', role: 'cut' },
        { label: 'Copy', accelerator: 'CmdOrCtrl+C', role: 'copy' },
        { label: 'Paste', accelerator: 'CmdOrCtrl+V', role: 'paste' },
        { label: 'Select All', accelerator: 'CmdOrCtrl+A', role: 'selectAll' },
        { type: 'separator' },
        {
          label: 'Find & Replace',
          accelerator: 'CmdOrCtrl+F',
          click: () => mainWindow.webContents.send('toggle-find')
        }
      ]
    },
    {
      label: 'View',
      submenu: [
        {
          label: 'Toggle Preview',
          accelerator: 'CmdOrCtrl+Shift+V',
          click: () => mainWindow.webContents.send('toggle-preview')
        },
        {
          label: 'Command Palette',
          accelerator: 'CmdOrCtrl+Shift+P',
          click: () => mainWindow.webContents.send('toggle-command-palette')
        },
        { type: 'separator' },
        {
          label: 'Sidebar',
          submenu: [
            { label: 'File Explorer', click: () => mainWindow.webContents.send('toggle-sidebar-panel', 'explorer') },
            { label: 'Git', click: () => mainWindow.webContents.send('toggle-sidebar-panel', 'git') },
            { label: 'Snippets', click: () => mainWindow.webContents.send('toggle-sidebar-panel', 'snippets') },
            { label: 'Templates', click: () => mainWindow.webContents.send('toggle-sidebar-panel', 'templates') }
          ]
        },
        {
          label: 'Bottom Panel (REPL)',
          click: () => mainWindow.webContents.send('toggle-bottom-panel')
        },
        { type: 'separator' },
        {
          label: 'Theme',
          submenu: [
            // Light Themes (grouped first)
            { label: 'Atom One Light (Default)', click: () => setTheme('atomonelight') },
            { label: 'GitHub Light', click: () => setTheme('github') },
            { label: 'Light', click: () => setTheme('light') },
            { label: 'Solarized Light', click: () => setTheme('solarized') },
            { label: 'Gruvbox Light', click: () => setTheme('gruvbox-light') },
            { label: 'Ayu Light', click: () => setTheme('ayu-light') },
            { label: 'Sepia', click: () => setTheme('sepia') },
            { label: 'Paper', click: () => setTheme('paper') },
            { label: 'Rose Pine Dawn', click: () => setTheme('rosepine-dawn') },
            { label: 'Concrete Light', click: () => setTheme('concrete-light') },
            { type: 'separator' },
            // Dark Themes
            { label: 'Dark', click: () => setTheme('dark') },
            { label: 'One Dark', click: () => setTheme('onedark') },
            { label: 'Dracula', click: () => setTheme('dracula') },
            { label: 'Nord', click: () => setTheme('nord') },
            { label: 'Monokai', click: () => setTheme('monokai') },
            { label: 'Material', click: () => setTheme('material') },
            { label: 'Gruvbox Dark', click: () => setTheme('gruvbox-dark') },
            { label: 'Tokyo Night', click: () => setTheme('tokyonight') },
            { label: 'Palenight', click: () => setTheme('palenight') },
            { label: 'Ayu Dark', click: () => setTheme('ayu-dark') },
            { label: 'Ayu Mirage', click: () => setTheme('ayu-mirage') },
            { label: 'Oceanic Next', click: () => setTheme('oceanic-next') },
            { label: 'Cobalt2', click: () => setTheme('cobalt2') },
            { label: 'Concrete Dark', click: () => setTheme('concrete-dark') },
            { label: 'Concrete Warm', click: () => setTheme('concrete-warm') }
          ]
        },
        { type: 'separator' },
        {
          label: 'Font Size',
          submenu: [
            { 
              label: 'Increase Font Size', 
              accelerator: 'CmdOrCtrl+Shift+Plus',
              click: () => mainWindow.webContents.send('adjust-font-size', 'increase')
            },
            { 
              label: 'Decrease Font Size', 
              accelerator: 'CmdOrCtrl+Shift+-',
              click: () => mainWindow.webContents.send('adjust-font-size', 'decrease')
            },
            { 
              label: 'Reset Font Size',
              accelerator: 'CmdOrCtrl+Shift+0',
              click: () => mainWindow.webContents.send('adjust-font-size', 'reset')
            }
          ]
        },
        { type: 'separator' },
        {
          label: 'Spell Check',
          type: 'checkbox',
          checked: true,
          click: (menuItem) => {
            mainWindow.webContents.session.setSpellCheckerEnabled(menuItem.checked);
          }
        },
        { type: 'separator' },
        {
          label: 'Custom Preview CSS',
          submenu: [
            {
              label: 'Load Custom Preview CSS...',
              click: () => mainWindow.webContents.send('load-custom-css')
            },
            {
              label: 'Clear Custom Preview CSS',
              click: () => mainWindow.webContents.send('clear-custom-css')
            }
          ]
        },
        { type: 'separator' },
        { label: 'Reload', accelerator: 'CmdOrCtrl+R', role: 'reload' },
        { label: 'Toggle DevTools', accelerator: 'F12', role: 'toggleDevTools' },
        { type: 'separator' },
        { label: 'Zoom In', accelerator: 'CmdOrCtrl+Plus', role: 'zoomIn' },
        { label: 'Zoom Out', accelerator: 'CmdOrCtrl+-', role: 'zoomOut' },
        { label: 'Reset Zoom', accelerator: 'CmdOrCtrl+0', role: 'resetZoom' }
      ]
    },
    {
      label: 'Batch',
      submenu: [
        {
          label: 'Convert Markdown Folder...',
          click: () => showBatchConversionDialog()
        },
        { type: 'separator' },
        {
          label: 'Batch Image Conversion...',
          click: () => mainWindow.webContents.send('show-batch-converter', 'image')
        },
        {
          label: 'Batch Audio Conversion...',
          click: () => mainWindow.webContents.send('show-batch-converter', 'audio')
        },
        {
          label: 'Batch Video Conversion...',
          click: () => mainWindow.webContents.send('show-batch-converter', 'video')
        },
        {
          label: 'Batch PDF Conversion...',
          click: () => mainWindow.webContents.send('show-batch-converter', 'pdf')
        }
      ]
    },
    {
      label: 'Convert',
      submenu: [
        {
          label: 'Universal File Converter...',
          accelerator: 'CmdOrCtrl+Shift+C',
          click: () => showUniversalConverterDialog()
        }
      ]
    },
    {
      label: 'PDF Editor',
      submenu: [
        {
          label: 'Open PDF File...',
          accelerator: 'CmdOrCtrl+Shift+O',
          click: () => openPDFFile()
        },
        { type: 'separator' },
        {
          label: 'Merge PDFs...',
          click: () => showPDFEditorDialog('merge')
        },
        {
          label: 'Split PDF...',
          click: () => showPDFEditorDialog('split')
        },
        {
          label: 'Compress PDF...',
          click: () => showPDFEditorDialog('compress')
        },
        {
          type: 'separator'
        },
        {
          label: 'Rotate Pages...',
          click: () => showPDFEditorDialog('rotate')
        },
        {
          label: 'Delete Pages...',
          click: () => showPDFEditorDialog('delete')
        },
        {
          label: 'Reorder Pages...',
          click: () => showPDFEditorDialog('reorder')
        },
        {
          type: 'separator'
        },
        {
          label: 'Add Watermark...',
          click: () => showPDFEditorDialog('watermark')
        },
        {
          type: 'separator'
        },
        {
          label: 'Security',
          submenu: [
            {
              label: 'Add Password Protection...',
              click: () => showPDFEditorDialog('encrypt')
            },
            {
              label: 'Remove Password...',
              click: () => showPDFEditorDialog('decrypt')
            },
            {
              label: 'Set Permissions...',
              click: () => showPDFEditorDialog('permissions')
            }
          ]
        },
        {
          type: 'separator'
        },
        {
          label: 'About PDF Editor',
          click: () => {
            dialog.showMessageBox(mainWindow, {
              type: 'info',
              title: 'About PDF Editor',
              message: 'PDF Editor',
              detail: 'Comprehensive PDF editing capabilities powered by pdf-lib.\n\nFeatures:\n• Merge multiple PDF files\n• Split PDF into separate files\n• Compress PDF to reduce file size\n• Rotate pages (90°, 180°, 270°)\n• Delete unwanted pages\n• Reorder pages\n• Add text watermarks\n\nSecurity Features:\n• Password protection (encryption)\n• Remove passwords (decryption)\n• Set document permissions\n\n100% offline and open-source.',
              buttons: ['OK']
            });
          }
        }
      ]
    },
    {
      label: 'Tools',
      submenu: [
        {
          label: 'Table Generator',
          accelerator: 'CmdOrCtrl+Shift+T',
          click: () => openTableGenerator()
        },
        {
          label: 'ASCII Art Generator',
          accelerator: 'CmdOrCtrl+Shift+A',
          click: () => openAsciiGenerator()
        },
        { type: 'separator' },
        {
          label: 'Document Compare',
          click: () => mainWindow.webContents.send('show-document-compare')
        }
      ]
    },
    {
      label: 'Help',
      submenu: [
        {
          label: 'About MarkdownConverter',
          click: () => showAboutDialog()
        },
        { type: 'separator' },
        {
          label: 'Dependencies & Requirements',
          click: () => showDependenciesDialog()
        },
        { type: 'separator' },
        {
          label: 'Documentation',
          click: () => shell.openExternal('https://github.com/amitwh/markdown-converter')
        },
        {
          label: 'Report Issue',
          click: () => shell.openExternal('https://github.com/amitwh/markdown-converter/issues')
        },
        {
          label: 'Check for Updates',
          click: () => shell.openExternal('https://github.com/amitwh/markdown-converter/releases')
        }
      ]
    }
  ];

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);
}

// Show About Dialog with logo
function showAboutDialog() {
  const aboutWindow = new BrowserWindow({
    width: 500,
    height: 600,
    parent: mainWindow,
    modal: true,
    resizable: false,
    minimizable: false,
    maximizable: false,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true
    },
    icon: path.join(__dirname, '../assets/icon.png')
  });

  // Convert images to base64 for data URL compatibility
  let logoBase64 = '';
  let iconBase64 = '';
  try {
    const logoPath = path.join(__dirname, '../assets/logo.png');
    const iconPath = path.join(__dirname, '../assets/icon.png');
    if (fs.existsSync(logoPath)) {
      logoBase64 = 'data:image/png;base64,' + fs.readFileSync(logoPath).toString('base64');
    }
    if (fs.existsSync(iconPath)) {
      iconBase64 = 'data:image/png;base64,' + fs.readFileSync(iconPath).toString('base64');
    }
  } catch (e) {
    console.error('Error loading about dialog images:', e);
  }

  const aboutHTML = `
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>About MarkdownConverter</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: 'Segoe UI', system-ui, sans-serif;
      background: linear-gradient(135deg, #464646 0%, #0d0b09 100%);
      color: #e3e3e3;
      padding: 30px;
      text-align: center;
    }
    .logo { width: 120px; margin-bottom: 20px; border-radius: 20px; }
    h1 { font-size: 24px; margin-bottom: 5px; color: #fff; }
    .version { color: #e5461f; font-size: 14px; margin-bottom: 20px; }
    .company { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 20px; }
    .company-logo { height: 24px; }
    .section { background: rgba(255,255,255,0.1); border-radius: 10px; padding: 15px; margin: 15px 0; text-align: left; }
    .section h3 { color: #e5461f; font-size: 14px; margin-bottom: 10px; }
    .section p, .section li { font-size: 12px; line-height: 1.6; }
    ul { padding-left: 20px; }
    .footer { margin-top: 20px; font-size: 11px; color: #9a9696; }
    a { color: #e5461f; text-decoration: none; }
    a:hover { text-decoration: underline; }
  </style>
</head>
<body>
  <img src="${iconBase64}" class="logo" alt="MarkdownConverter">
  <h1>MarkdownConverter</h1>
  <div class="version">Version ${app.getVersion()}</div>

  <div class="company">
    <span>by</span>
    <img src="${logoBase64}" class="company-logo" alt="ConcreteInfo">
  </div>

  <div class="section">
    <h3>Features</h3>
    <ul>
      <li>Professional Markdown editing with syntax highlighting</li>
      <li>Universal file converter (Image, Audio, Video, PDF)</li>
      <li>Batch conversion for all media types</li>
      <li>Advanced PDF Editor (merge, split, watermark, encrypt)</li>
      <li>Export to PDF, DOCX, HTML, LaTeX, EPUB & more</li>
      <li>23+ beautiful themes including ConcreteInfo theme</li>
      <li>ASCII Art & Table generators</li>
      <li>Code file syntax highlighting</li>
    </ul>
  </div>

  <div class="section">
    <h3>Contact</h3>
    <p>Email: <a href="mailto:amit.wh@gmail.com">amit.wh@gmail.com</a></p>
    <p>Website: <a href="https://github.com/amitwh/markdown-converter">GitHub Repository</a></p>
  </div>

  <div class="footer">
    <p>License: MIT</p>
    <p>© 2024-2026 ConcreteInfo. All rights reserved.</p>
  </div>
</body>
</html>`;

  aboutWindow.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(aboutHTML));
  aboutWindow.setMenuBarVisibility(false);
}

// Show Dependencies Dialog
function showDependenciesDialog() {
  const depsWindow = new BrowserWindow({
    width: 600,
    height: 700,
    parent: mainWindow,
    modal: true,
    resizable: true,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true
    },
    icon: path.join(__dirname, '../assets/icon.png')
  });

  const depsHTML = `
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Dependencies & Requirements</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: 'Segoe UI', system-ui, sans-serif;
      background: #f5f5f5;
      color: #464646;
      padding: 30px;
    }
    h1 { color: #e5461f; font-size: 20px; margin-bottom: 20px; border-bottom: 2px solid #e5461f; padding-bottom: 10px; }
    h2 { color: #464646; font-size: 16px; margin: 20px 0 10px; }
    .dep-card {
      background: #fff;
      border-radius: 8px;
      padding: 15px;
      margin: 10px 0;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
    .dep-name { font-weight: bold; color: #0d0b09; }
    .dep-desc { font-size: 13px; color: #666; margin: 5px 0; }
    .dep-link { color: #e5461f; font-size: 12px; text-decoration: none; }
    .dep-link:hover { text-decoration: underline; }
    .required { background: #fff3cd; border-left: 4px solid #ffc107; }
    .optional { background: #d4edda; border-left: 4px solid #28a745; }
    .tag { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; margin-left: 10px; }
    .tag-required { background: #ffc107; color: #000; }
    .tag-optional { background: #28a745; color: #fff; }
  </style>
</head>
<body>
  <h1>Dependencies & Requirements</h1>

  <h2>Required Dependencies</h2>

  <div class="dep-card required">
    <div class="dep-name">Pandoc <span class="tag tag-required">Required</span></div>
    <div class="dep-desc">Universal document converter. Required for most export formats (PDF, DOCX, LaTeX, EPUB).</div>
    <a class="dep-link" href="https://pandoc.org/installing.html" target="_blank">https://pandoc.org/installing.html</a>
  </div>

  <h2>Optional Dependencies (for extended features)</h2>

  <div class="dep-card optional">
    <div class="dep-name">FFmpeg <span class="tag tag-optional">Optional</span></div>
    <div class="dep-desc">Required for audio/video conversion and processing.</div>
    <a class="dep-link" href="https://ffmpeg.org/download.html" target="_blank">https://ffmpeg.org/download.html</a>
  </div>

  <div class="dep-card optional">
    <div class="dep-name">ImageMagick <span class="tag tag-optional">Optional</span></div>
    <div class="dep-desc">Required for image format conversion and processing.</div>
    <a class="dep-link" href="https://imagemagick.org/script/download.php" target="_blank">https://imagemagick.org/script/download.php</a>
  </div>

  <div class="dep-card optional">
    <div class="dep-name">LibreOffice <span class="tag tag-optional">Optional</span></div>
    <div class="dep-desc">Required for enhanced document conversion (Office formats).</div>
    <a class="dep-link" href="https://www.libreoffice.org/download/download/" target="_blank">https://www.libreoffice.org/download/download/</a>
  </div>

  <div class="dep-card optional">
    <div class="dep-name">MiKTeX / TeX Live <span class="tag tag-optional">Optional</span></div>
    <div class="dep-desc">Required for PDF export via LaTeX (higher quality PDFs).</div>
    <a class="dep-link" href="https://miktex.org/download" target="_blank">https://miktex.org/download</a>
  </div>

  <h2>Bundled Libraries</h2>

  <div class="dep-card">
    <div class="dep-name">pdf-lib</div>
    <div class="dep-desc">PDF manipulation library for merge, split, watermark, and encryption features.</div>
  </div>

  <div class="dep-card">
    <div class="dep-name">marked</div>
    <div class="dep-desc">Markdown parser for preview rendering.</div>
  </div>

  <div class="dep-card">
    <div class="dep-name">highlight.js</div>
    <div class="dep-desc">Syntax highlighting for code blocks.</div>
  </div>

  <div class="dep-card">
    <div class="dep-name">DOMPurify</div>
    <div class="dep-desc">HTML sanitization for security.</div>
  </div>
</body>
</html>`;

  depsWindow.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(depsHTML));
  depsWindow.setMenuBarVisibility(false);
}

// Open PDF File for viewing/editing
function openPDFFile() {
  const files = dialog.showOpenDialogSync(mainWindow, {
    properties: ['openFile'],
    filters: [
      { name: 'PDF Files', extensions: ['pdf'] }
    ]
  });

  if (files && files[0]) {
    const stats = fs.statSync(files[0]);
    if (stats.size > MAX_FILE_SIZE) {
        dialog.showErrorBox('File Too Large', `File exceeds the ${MAX_FILE_SIZE_MB}MB size limit.`);
        return;
    }
    mainWindow.webContents.send('open-pdf-viewer', files[0]);
  }
}

function openFile() {
  const files = dialog.showOpenDialogSync(mainWindow, {
    properties: ['openFile'],
    filters: [
      { name: 'Markdown', extensions: ['md', 'markdown'] },
      { name: 'Developer Formats', extensions: ['json', 'yaml', 'yml', 'xml', 'toml'] },
      { name: 'All Files', extensions: ['*'] }
    ]
  });

  if (files && files[0]) {
    const stats = fs.statSync(files[0]);
    if (stats.size > MAX_FILE_SIZE) {
        dialog.showErrorBox('File Too Large', `File exceeds the ${MAX_FILE_SIZE_MB}MB size limit.`);
        return;
    }
    currentFile = files[0];
    const ext = path.extname(currentFile).toLowerCase().slice(1);
    let content = fs.readFileSync(currentFile, 'utf-8');

    // Wrap developer format files in code blocks for markdown display
    const devFormats = ['json', 'yaml', 'yml', 'xml', 'toml'];
    if (devFormats.includes(ext)) {
      content = convertDataToMarkdown(content, ext);
    }

    mainWindow.webContents.send('file-opened', { path: currentFile, content });
  }
}

function openPdfFile() {
  const files = dialog.showOpenDialogSync(mainWindow, {
    properties: ['openFile'],
    filters: [
      { name: 'PDF Files', extensions: ['pdf'] },
      { name: 'All Files', extensions: ['*'] }
    ]
  });

  if (files && files[0]) {
    const stats = fs.statSync(files[0]);
    if (stats.size > MAX_FILE_SIZE) {
        dialog.showErrorBox('File Too Large', `File exceeds the ${MAX_FILE_SIZE_MB}MB size limit.`);
        return;
    }
    mainWindow.webContents.send('open-pdf-file', files[0]);
  }
}

function saveAsFile() {
  const file = dialog.showSaveDialogSync(mainWindow, {
    defaultExt: '.md',
    filters: [
      { name: 'Markdown', extensions: ['md', 'markdown'] },
      { name: 'All Files', extensions: ['*'] }
    ]
  });

  if (file) {
    currentFile = file;
    mainWindow.webContents.send('get-content-for-save', file);
  }
}

function exportFile(format) {
  if (!currentFile) {
    dialog.showErrorBox('Error', 'Please save the file first');
    return;
  }

  // Show export options dialog
  showExportOptionsDialog(format);
}

function showExportOptionsDialog(format) {
  mainWindow.webContents.send('show-export-dialog', format);
}

function showBatchConversionDialog() {
  mainWindow.webContents.send('show-batch-dialog');
}

// Select Word Template
async function selectWordTemplate() {
  const result = await dialog.showOpenDialog(mainWindow, {
    title: 'Select Word Template',
    filters: [{ name: 'Word Document', extensions: ['docx'] }],
    properties: ['openFile']
  });

  if (!result.canceled && result.filePaths.length > 0) {
    wordTemplatePath = result.filePaths[0];
    store.set('wordTemplatePath', wordTemplatePath);

    dialog.showMessageBox(mainWindow, {
      type: 'info',
      title: 'Template Selected',
      message: 'Word template has been updated',
      detail: `Template: ${path.basename(wordTemplatePath)}`
    });
  }
}

// Template Settings Dialog
async function showTemplateSettings() {
  const result = await dialog.showMessageBox(mainWindow, {
    type: 'question',
    title: 'Template Settings',
    message: 'Configure Word Template Export',
    detail: `Current template: ${wordTemplatePath ? path.basename(wordTemplatePath) : 'Default template'}\nContent starts from page: ${templateStartPage}\n\nWhich page should content start from?\n(Templates usually have cover pages, TOC, etc.)`,
    buttons: ['Page 1', 'Page 2', 'Page 3', 'Page 4', 'Page 5', 'Custom...', 'Cancel'],
    defaultId: templateStartPage - 1,
    cancelId: 6
  });

  if (result.response === 6) return; // Cancel

  let newStartPage;
  if (result.response === 5) { // Custom
    // Show input dialog for custom page number
    mainWindow.webContents.send('show-custom-start-page-dialog', templateStartPage);
  } else {
    newStartPage = result.response + 1; // Convert button index to page number
    templateStartPage = newStartPage;
    store.set('templateStartPage', templateStartPage);

    dialog.showMessageBox(mainWindow, {
      type: 'info',
      title: 'Settings Updated',
      message: 'Template settings have been updated',
      detail: `Content will now start from page ${templateStartPage}`
    });
  }
}

// Handle custom start page input from renderer
ipcMain.on('set-custom-start-page', (event, pageNumber) => {
  const page = parseInt(pageNumber);
  if (page >= 1 && page <= 100) {
    templateStartPage = page;
    store.set('templateStartPage', templateStartPage);

    dialog.showMessageBox(mainWindow, {
      type: 'info',
      title: 'Settings Updated',
      message: 'Template settings have been updated',
      detail: `Content will now start from page ${templateStartPage}`
    });
  } else {
    dialog.showErrorBox('Invalid Page Number', 'Please enter a page number between 1 and 100');
  }
});

// Header & Footer Settings IPC Handlers

// Get current header/footer settings
ipcMain.on('get-header-footer-settings', (event) => {
  event.reply('header-footer-settings-data', headerFooterSettings);
});

// Save header/footer settings
ipcMain.on('save-header-footer-settings', (event, settings) => {
  headerFooterSettings = settings;
  store.set('headerFooterSettings', headerFooterSettings);

  dialog.showMessageBox(mainWindow, {
    type: 'info',
    title: 'Settings Saved',
    message: 'Header and footer settings have been saved successfully!',
    buttons: ['OK']
  });
});

// Get current page settings
ipcMain.on('get-page-settings', (event) => {
  event.reply('page-settings-data', pageSettings);
});

// Update page settings from export dialog
ipcMain.on('update-page-settings', (event, settings) => {
  pageSettings = settings;
  store.set('pageSettings', pageSettings);
  console.log('Page settings updated:', pageSettings);
});

// Save header/footer logo image
// Browse for header/footer logo
ipcMain.on('browse-header-footer-logo', async (event, position) => {
  try {
    const result = await dialog.showOpenDialog(mainWindow, {
      title: `Select ${position.charAt(0).toUpperCase() + position.slice(1)} Logo/Image`,
      filters: [
        { name: 'Images', extensions: ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg', 'webp'] }
      ],
      properties: ['openFile']
    });

    if (!result.canceled && result.filePaths.length > 0) {
      const filePath = result.filePaths[0];

      // Copy image to userData directory for persistent storage
      const userDataPath = app.getPath('userData');
      const logoDir = path.join(userDataPath, 'logos');

      // Create logos directory if it doesn't exist
      if (!fs.existsSync(logoDir)) {
        fs.mkdirSync(logoDir, { recursive: true });
      }

      // Generate unique filename
      const ext = path.extname(filePath);
      const filename = `${position}_${Date.now()}${ext}`;
      const destPath = path.join(logoDir, filename);

      // Copy file
      fs.copyFileSync(filePath, destPath);

      // Update settings
      if (position === 'header') {
        headerFooterSettings.header.logo = destPath;
      } else if (position === 'footer') {
        headerFooterSettings.footer.logo = destPath;
      }

      event.reply('header-footer-logo-saved', { position, path: destPath });
    }
  } catch (error) {
    console.error('Logo browse error:', error);
    dialog.showErrorBox('Logo Error', sanitizeErrorMessage(`Failed to select logo: ${error.message}`));
  }
});

ipcMain.on('save-header-footer-logo', async (event, { position, filePath }) => {
  try {
    if (!filePath) {
      dialog.showErrorBox('Logo Error', 'Failed to save logo: The "path" argument must be of type string. Received undefined');
      return;
    }

    // Copy image to userData directory for persistent storage
    const userDataPath = app.getPath('userData');
    const logoDir = path.join(userDataPath, 'logos');

    // Create logos directory if it doesn't exist
    if (!fs.existsSync(logoDir)) {
      fs.mkdirSync(logoDir, { recursive: true });
    }

    // Verify source file exists
    if (!fs.existsSync(filePath)) {
      dialog.showErrorBox('Logo Error', sanitizeErrorMessage(`Source file not found: ${filePath}`));
      return;
    }

    // Generate unique filename
    const ext = path.extname(filePath);
    const filename = `${position}_${Date.now()}${ext}`;
    const destPath = path.join(logoDir, filename);

    // Copy file
    fs.copyFileSync(filePath, destPath);

    // Update settings
    if (position === 'header') {
      headerFooterSettings.header.logo = destPath;
    } else if (position === 'footer') {
      headerFooterSettings.footer.logo = destPath;
    }

    event.reply('header-footer-logo-saved', { position, path: destPath });
  } catch (error) {
    console.error('Logo save error:', error);
    dialog.showErrorBox('Logo Error', sanitizeErrorMessage(`Failed to save logo: ${error.message}`));
  }
});

// Clear header/footer logo
ipcMain.on('clear-header-footer-logo', (event, position) => {
  if (position === 'header') {
    headerFooterSettings.header.logo = null;
  } else if (position === 'footer') {
    headerFooterSettings.footer.logo = null;
  }
  event.reply('header-footer-logo-cleared', position);
});

// Helper function to process dynamic fields in header/footer text
function processDynamicFields(text, metadata = {}) {
  if (!text) return '';

  const now = new Date();
  const dateStr = now.toLocaleDateString();
  const timeStr = now.toLocaleTimeString();

  let result = text;
  result = result.replace(/\$DATE\$/g, dateStr);
  result = result.replace(/\$TIME\$/g, timeStr);
  result = result.replace(/\$TITLE\$/g, metadata.title || 'Untitled');
  result = result.replace(/\$AUTHOR\$/g, metadata.author || '');
  result = result.replace(/\$FILENAME\$/g, metadata.filename || '');

  // Note: $PAGE$ and $TOTAL$ are handled by Pandoc/export tools

  return result;
}

// Add headers/footers to DOCX file using PizZip and docx4js
// Function to set page size in DOCX files
async function setDocxPageSize(docxPath) {
  try {
    const PizZip = require('pizzip');

    // Read the DOCX file
    const docxBuffer = fs.readFileSync(docxPath);
    const zip = new PizZip(docxBuffer);

    // Get document.xml
    let documentXml = zip.file('word/document.xml').asText();

    // Get page dimensions
    let width, height;
    const pageSize = PAGE_SIZES[pageSettings.size];

    if (pageSize) {
      width = pageSize.word.width;
      height = pageSize.word.height;
    } else if (pageSettings.customWidth && pageSettings.customHeight) {
      // Parse custom dimensions (convert to twentieths of a point)
      // Note: This is simplified - production code should handle various units
      width = parseInt(pageSettings.customWidth) || 11906;
      height = parseInt(pageSettings.customHeight) || 16838;
    } else {
      // Default to A4
      width = 11906;
      height = 16838;
    }

    // Swap dimensions for landscape
    if (pageSettings.orientation === 'landscape') {
      [width, height] = [height, width];
    }

    // Update all <w:pgSz> elements in section properties
    const pgSzRegex = /<w:pgSz[^>]*\/>/g;
    documentXml = documentXml.replace(pgSzRegex, () => {
      return `<w:pgSz w:w="${width}" w:h="${height}" w:orient="${pageSettings.orientation}"/>`;
    });

    // If no pgSz found, add it to all sectPr elements
    if (!pgSzRegex.test(documentXml)) {
      const sectPrRegex = /<w:sectPr[^>]*>/g;
      documentXml = documentXml.replace(sectPrRegex, (match) => {
        return `${match}<w:pgSz w:w="${width}" w:h="${height}" w:orient="${pageSettings.orientation}"/>`;
      });
    }

    // Save updated document.xml
    zip.file('word/document.xml', documentXml);

    // Write modified DOCX
    const newDocxBuffer = zip.generate({ type: 'nodebuffer' });
    fs.writeFileSync(docxPath, newDocxBuffer);

  } catch (error) {
    console.error('Failed to set DOCX page size:', error);
  }
}

async function addHeaderFooterToDocx(docxPath, metadata = {}) {
  if (!headerFooterSettings.enabled) return;

  try {
    const PizZip = require('pizzip');

    // Read the DOCX file
    const docxBuffer = fs.readFileSync(docxPath);
    const zip = new PizZip(docxBuffer);

    // Process dynamic fields
    const headerLeft = processDynamicFields(headerFooterSettings.header.left, metadata);
    const headerCenter = processDynamicFields(headerFooterSettings.header.center, metadata);
    const headerRight = processDynamicFields(headerFooterSettings.header.right, metadata);
    const footerLeft = processDynamicFields(headerFooterSettings.footer.left, metadata);
    const footerCenter = processDynamicFields(headerFooterSettings.footer.center, metadata);
    const footerRight = processDynamicFields(headerFooterSettings.footer.right, metadata);

    // Create header XML
    if (headerLeft || headerCenter || headerRight) {
      const headerXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:hdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:p>
    <w:pPr><w:jc w:val="left"/></w:pPr>
    <w:r><w:t>${headerLeft || ''}</w:t></w:r>
  </w:p>
  <w:p>
    <w:pPr><w:jc w:val="center"/></w:pPr>
    <w:r><w:t>${headerCenter || ''}</w:t></w:r>
  </w:p>
  <w:p>
    <w:pPr><w:jc w:val="right"/></w:pPr>
    <w:r><w:t>${headerRight || ''}</w:t></w:r>
  </w:p>
</w:hdr>`;
      zip.file('word/header1.xml', headerXml);
    }

    // Create footer XML with page numbers
    if (footerLeft || footerCenter || footerRight) {
      let footerCenterXml = '';
      if (footerCenter) {
        // Handle $PAGE$ and $TOTAL$ in footer
        if (footerCenter.includes('$PAGE$') || footerCenter.includes('$TOTAL$')) {
          const parts = footerCenter.split(/(\$PAGE\$|\$TOTAL\$)/);
          footerCenterXml = parts.map(part => {
            if (part === '$PAGE$') {
              return '<w:fldSimple w:instr="PAGE"/>';
            } else if (part === '$TOTAL$') {
              return '<w:fldSimple w:instr="NUMPAGES"/>';
            } else {
              return `<w:r><w:t>${part}</w:t></w:r>`;
            }
          }).join('');
        } else {
          footerCenterXml = `<w:r><w:t>${footerCenter}</w:t></w:r>`;
        }
      }

      const footerXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:ftr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:p>
    <w:pPr><w:jc w:val="left"/></w:pPr>
    <w:r><w:t>${footerLeft || ''}</w:t></w:r>
  </w:p>
  <w:p>
    <w:pPr><w:jc w:val="center"/></w:pPr>
    ${footerCenterXml}
  </w:p>
  <w:p>
    <w:pPr><w:jc w:val="right"/></w:pPr>
    <w:r><w:t>${footerRight || ''}</w:t></w:r>
  </w:p>
</w:ftr>`;
      zip.file('word/footer1.xml', footerXml);
    }

    // Update document.xml.rels to reference header/footer
    let relsXml = zip.file('word/_rels/document.xml.rels').asText();

    // Add header relationship if not exists
    if ((headerLeft || headerCenter || headerRight) && !relsXml.includes('header1.xml')) {
      const headerId = 'rId100';
      const headerRel = `<Relationship Id="${headerId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" Target="header1.xml"/>`;
      relsXml = relsXml.replace('</Relationships>', headerRel + '</Relationships>');
    }

    // Add footer relationship if not exists
    if ((footerLeft || footerCenter || footerRight) && !relsXml.includes('footer1.xml')) {
      const footerId = 'rId101';
      const footerRel = `<Relationship Id="${footerId}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" Target="footer1.xml"/>`;
      relsXml = relsXml.replace('</Relationships>', footerRel + '</Relationships>');
    }

    zip.file('word/_rels/document.xml.rels', relsXml);

    // Update document.xml to use header/footer in sections
    let documentXml = zip.file('word/document.xml').asText();
    if ((headerLeft || headerCenter || headerRight || footerLeft || footerCenter || footerRight)) {
      // Find all section properties and add header/footer references
      const sectPrRegex = /<w:sectPr[^>]*>[\s\S]*?<\/w:sectPr>/g;
      documentXml = documentXml.replace(sectPrRegex, (match) => {
        let updated = match;
        if ((headerLeft || headerCenter || headerRight) && !match.includes('headerReference')) {
          updated = updated.replace('</w:sectPr>', '<w:headerReference w:type="default" r:id="rId100"/></w:sectPr>');
        }
        if ((footerLeft || footerCenter || footerRight) && !match.includes('footerReference')) {
          updated = updated.replace('</w:sectPr>', '<w:footerReference w:type="default" r:id="rId101"/></w:sectPr>');
        }
        return updated;
      });
    }

    zip.file('word/document.xml', documentXml);

    // Write modified DOCX
    const newDocxBuffer = zip.generate({ type: 'nodebuffer' });
    fs.writeFileSync(docxPath, newDocxBuffer);

  } catch (error) {
    console.error('Failed to add headers/footers to DOCX:', error);
    // Don't fail the export, just log the error
  }
}

// Enhanced Word Export with Template Support
async function exportWordWithTemplate() {
  if (!currentFile) {
    dialog.showErrorBox('Error', 'Please save the file first');
    return;
  }

  try {
    // Get markdown content
    const content = fs.readFileSync(currentFile, 'utf-8');

    // Show dialog for output file
    const result = await dialog.showSaveDialog(mainWindow, {
      title: 'Export to Word (Enhanced)',
      defaultPath: currentFile.replace(/\.md$/, '.docx'),
      filters: [{ name: 'Word Document', extensions: ['docx'] }]
    });

    if (result.canceled) return;

    // Create exporter instance with selected template, start page, and page settings
    const exporter = new WordTemplateExporter(wordTemplatePath, templateStartPage, pageSettings);

    // Convert markdown to DOCX
    await exporter.convert(content, result.filePath);

    dialog.showMessageBox(mainWindow, {
      type: 'info',
      title: 'Export Successful',
      message: 'Document exported successfully!',
      detail: `Saved to: ${result.filePath}`
    });

  } catch (error) {
    dialog.showErrorBox('Export Error', sanitizeErrorMessage(`Failed to export document: ${error.message}`));
  }
}

// Enhanced PDF Export via Word Template
async function exportPDFViaWordTemplate() {
  if (!currentFile) {
    dialog.showErrorBox('Error', 'Please save the file first');
    return;
  }

  try {
    // Get markdown content
    const content = fs.readFileSync(currentFile, 'utf-8');

    // Show dialog for output file
    const result = await dialog.showSaveDialog(mainWindow, {
      title: 'Export to PDF (Enhanced)',
      defaultPath: currentFile.replace(/\.md$/, '.pdf'),
      filters: [{ name: 'PDF Document', extensions: ['pdf'] }]
    });

    if (result.canceled) return;

    // Step 1: Create temporary DOCX file using Word template
    const tempDocxPath = result.filePath.replace(/\.pdf$/, '_temp.docx');

    const exporter = new WordTemplateExporter(wordTemplatePath, templateStartPage);
    await exporter.convert(content, tempDocxPath);

    // Step 2: Convert DOCX to PDF using LibreOffice (using execFile for safety)
    const soffice = process.platform === 'win32'
      ? 'C:\\Program Files\\LibreOffice\\program\\soffice.exe'
      : 'soffice';

    const outputDir = path.dirname(result.filePath);
    const sofficeArgs = ['--headless', '--convert-to', 'pdf', '--outdir', outputDir, tempDocxPath];

    execFile(soffice, sofficeArgs, (error, stdout, stderr) => {
      // Clean up temporary DOCX file
      try {
        fs.unlinkSync(tempDocxPath);
      } catch (e) {
        console.error('Failed to delete temp file:', e);
      }

      if (error) {
        dialog.showErrorBox('PDF Conversion Error',
          sanitizeErrorMessage(`Failed to convert to PDF. Please ensure LibreOffice is installed.\n\nError: ${error.message}`));
        return;
      }

      // LibreOffice creates file with same base name as input
      const generatedPdfPath = tempDocxPath.replace(/\.docx$/, '.pdf');

      // Rename if needed
      if (generatedPdfPath !== result.filePath) {
        try {
          fs.renameSync(generatedPdfPath, result.filePath);
        } catch (e) {
          console.error('Failed to rename PDF:', e);
        }
      }

      dialog.showMessageBox(mainWindow, {
        type: 'info',
        title: 'Export Successful',
        message: 'PDF exported successfully using Word template!',
        detail: `Saved to: ${result.filePath}`
      });
    });

  } catch (error) {
    dialog.showErrorBox('Export Error', sanitizeErrorMessage(`Failed to export PDF: ${error.message}`));
  }
}

// Universal File Converter integration
function showUniversalConverterDialog() {
  mainWindow.webContents.send('show-universal-converter-dialog');
}

// PDF Editor dialog
function showPDFEditorDialog(operation) {
  mainWindow.webContents.send('show-pdf-editor-dialog', operation);
}

// Handle PDF editor from toolbar (with optional file path)
ipcMain.on('show-pdf-editor-from-toolbar', (event, { operation, filePath }) => {
  mainWindow.webContents.send('show-pdf-editor-dialog', operation, filePath);
});

// Check if conversion tool is available (using execFile for safety)
function checkConverterAvailable(tool) {
  return new Promise((resolve) => {
    const isWin = process.platform === 'win32';
    const locateCmd = isWin ? 'where' : 'which';
    let toolName;

    switch (tool) {
      case 'libreoffice':
        toolName = 'soffice';
        break;
      case 'imagemagick':
        toolName = isWin ? 'magick' : 'convert';
        break;
      case 'ffmpeg': {
        // ffmpeg-static is always bundled — check it directly
        const ffmpegBin = getFFmpegPath();
        resolve(fs.existsSync(ffmpegBin) || ffmpegBin === 'ffmpeg');
        return;
      }
      default:
        resolve(false);
        return;
    }

    execFile(locateCmd, [toolName], (error) => {
      resolve(!error);
    });
  });
}

// Handle universal file conversion
ipcMain.on('universal-convert', async (event, { tool, fromFormat, toFormat, filePath }) => {
  if (!conversionLimiter()) {
    mainWindow.webContents.send('conversion-status', 'Please wait before converting again...');
    return;
  }
  try {
    mainWindow.webContents.send('conversion-status', 'Checking converter availability...');

    // Check if the required tool is available
    const toolAvailable = await checkConverterAvailable(tool);

    if (!toolAvailable) {
      throw new Error(`${tool} is not installed or not found in PATH. Please install it first.`);
    }

    mainWindow.webContents.send('conversion-status', 'Converting file...');

    const outputPath = filePath.replace(/\.[^/.]+$/, `.${toFormat}`);
    let conversionInfo;

    switch (tool) {
      case 'libreoffice':
        conversionInfo = convertWithLibreOffice(filePath, toFormat, outputPath);
        break;
      case 'imagemagick':
        conversionInfo = convertWithImageMagick(filePath, outputPath);
        break;
      case 'ffmpeg':
        conversionInfo = convertWithFFmpeg(filePath, outputPath);
        break;
      case 'pandoc':
        conversionInfo = convertWithPandoc(filePath, outputPath);
        break;
      default:
        throw new Error(`Unknown conversion tool: ${tool}`);
    }

    // Use execFile for safety (prevents command injection)
    execFile(conversionInfo.command, conversionInfo.args, (error, stdout, stderr) => {
      if (error) {
        mainWindow.webContents.send('conversion-complete', {
          success: false,
          error: error.message
        });

        dialog.showMessageBox(mainWindow, {
          type: 'error',
          title: 'Conversion Failed',
          message: `${tool} conversion failed`,
          detail: stderr || error.message,
          buttons: ['OK']
        });
      } else {
        mainWindow.webContents.send('conversion-complete', {
          success: true,
          outputPath: outputPath
        });

        dialog.showMessageBox(mainWindow, {
          type: 'info',
          title: 'Conversion Complete',
          message: 'File converted successfully!',
          detail: `Saved to: ${outputPath}`,
          buttons: ['OK']
        });
      }
    });
  } catch (error) {
    mainWindow.webContents.send('conversion-complete', {
      success: false,
      error: error.message
    });

    dialog.showMessageBox(mainWindow, {
      type: 'error',
      title: 'Conversion Failed',
      message: 'Universal conversion failed',
      detail: error.message,
      buttons: ['OK']
    });
  }
});

// Handle universal batch file conversion
ipcMain.on('universal-convert-batch', async (event, { tool, fromFormat, toFormat, inputFolder, outputFolder, includeSubfolders, advancedOptions }) => {
  if (!conversionLimiter()) {
    mainWindow.webContents.send('conversion-status', 'Please wait before converting again...');
    return;
  }
  try {
    const toolAvailable = await checkConverterAvailable(tool);
    if (!toolAvailable) {
      throw new Error(`${tool} is not installed or not found in PATH. Please install it first.`);
    }

    // Collect matching files
    const files = [];
    function collectFiles(dir) {
      const entries = fs.readdirSync(dir, { withFileTypes: true });
      for (const entry of entries) {
        const fullPath = path.join(dir, entry.name);
        if (entry.isDirectory() && includeSubfolders) {
          collectFiles(fullPath);
        } else if (entry.isFile() && entry.name.toLowerCase().endsWith(`.${fromFormat}`)) {
          files.push(fullPath);
        }
      }
    }
    collectFiles(inputFolder);

    if (files.length === 0) {
      mainWindow.webContents.send('conversion-complete', { success: false, error: `No .${fromFormat} files found in the selected folder.` });
      return;
    }

    let completed = 0;
    let failed = 0;

    for (const filePath of files) {
      const relativePath = path.relative(inputFolder, filePath);
      const outputPath = path.join(outputFolder, relativePath.replace(/\.[^/.]+$/, `.${toFormat}`));

      // Ensure output subdirectory exists
      fs.mkdirSync(path.dirname(outputPath), { recursive: true });

      mainWindow.webContents.send('conversion-status', `Converting ${completed + 1}/${files.length}: ${path.basename(filePath)}`);

      let conversionInfo;
      switch (tool) {
        case 'libreoffice': conversionInfo = convertWithLibreOffice(filePath, toFormat, outputPath); break;
        case 'imagemagick': conversionInfo = convertWithImageMagick(filePath, outputPath); break;
        case 'ffmpeg': conversionInfo = convertWithFFmpeg(filePath, outputPath); break;
        case 'pandoc': conversionInfo = convertWithPandoc(filePath, outputPath); break;
        default: throw new Error(`Unknown conversion tool: ${tool}`);
      }

      await new Promise((resolve) => {
        execFile(conversionInfo.command, conversionInfo.args, (error) => {
          if (error) { failed++; } else { completed++; }
          resolve();
        });
      });
    }

    mainWindow.webContents.send('conversion-complete', {
      success: true,
      outputPath: outputFolder
    });

    dialog.showMessageBox(mainWindow, {
      type: 'info',
      title: 'Batch Conversion Complete',
      message: `Batch conversion finished!`,
      detail: `Converted: ${completed}/${files.length} files${failed > 0 ? ` (${failed} failed)` : ''}\nOutput: ${outputFolder}`,
      buttons: ['OK']
    });
  } catch (error) {
    mainWindow.webContents.send('conversion-complete', { success: false, error: error.message });
    dialog.showMessageBox(mainWindow, {
      type: 'error',
      title: 'Batch Conversion Failed',
      message: 'Batch conversion failed',
      detail: error.message,
      buttons: ['OK']
    });
  }
});

// LibreOffice conversion - returns {command, args} for execFile (safer than exec)
function convertWithLibreOffice(inputFile, outputFormat, outputPath) {
  const outputDir = path.dirname(outputPath);
  const soffice = process.platform === 'win32'
    ? 'C:\\Program Files\\LibreOffice\\program\\soffice.exe'
    : 'soffice';

  // LibreOffice conversion format mapping
  const formatMap = {
    'pdf': 'pdf',
    'docx': 'docx',
    'doc': 'doc',
    'odt': 'odt',
    'rtf': 'rtf',
    'txt': 'txt',
    'html': 'html',
    'xlsx': 'xlsx',
    'xls': 'xls',
    'ods': 'ods',
    'csv': 'csv',
    'pptx': 'pptx',
    'ppt': 'ppt',
    'odp': 'odp'
  };

  const format = formatMap[outputFormat] || outputFormat;

  // Return command and args for execFile
  return {
    command: soffice,
    args: ['--headless', '--convert-to', format, '--outdir', outputDir, inputFile]
  };
}

// ImageMagick conversion - returns {command, args} for execFile
function convertWithImageMagick(inputFile, outputPath) {
  const magick = process.platform === 'win32' ? 'magick' : 'convert';
  return {
    command: magick,
    args: [inputFile, outputPath]
  };
}

// FFmpeg conversion - returns {command, args} for execFile
function convertWithFFmpeg(inputFile, outputPath) {
  return {
    command: getFFmpegPath(),
    args: ['-i', inputFile, outputPath, '-y'],
  };
}

// Pandoc conversion - returns {command, args} for execFile
function convertWithPandoc(inputFile, outputPath) {
  return {
    command: 'pandoc',
    args: [inputFile, '-o', outputPath]
  };
}

function performExportWithOptions(format, options) {
  // Map format names to file extensions
  const formatExtMap = {
    revealjs: 'html',
    beamer: 'pdf',
    confluence: 'txt',
    jira: 'txt',
  };
  const fileExt = formatExtMap[format] || format;

  const outputFile = dialog.showSaveDialogSync(mainWindow, {
    defaultPath: currentFile.replace(/\.[^/.]+$/, `.${fileExt}`),
    filters: [
      { name: format.toUpperCase(), extensions: [fileExt] }
    ]
  });

  if (!outputFile) return; // User cancelled

  console.log(`Attempting to export ${format} to:`, outputFile);

  // Check pandoc availability first
  checkPandocAvailability().then((hasPandoc) => {
    console.log('Pandoc available:', hasPandoc);
    
    if (!hasPandoc) {
      // Handle formats that don't require pandoc
      if (format === 'html') {
        console.log('Using built-in HTML export');
        exportToHTML(outputFile);
        return;
      } else if (format === 'pdf') {
        console.log('Using built-in PDF export');
        exportToPDFElectron(outputFile);
        return;
      } else {
        dialog.showErrorBox('Export Error', 
          `Pandoc is required for ${format.toUpperCase()} export but is not installed or not found in PATH.\n\n` +
          `Please install Pandoc from: https://pandoc.org/installing.html\n\n` +
          `Alternatively, you can export to HTML or PDF using the built-in converters.`
        );
        return;
      }
    }

    // Use pandoc for export with advanced options
    console.log('Using Pandoc for export');
    let pandocCmd = `${getPandocPath()} "${currentFile}" -o "${outputFile}"`;

    // Add template if specified
    if (options.template && options.template !== 'default') {
      pandocCmd += ` --template="${options.template}"`;
    }

    // Add metadata
    if (options.metadata) {
      for (const [key, value] of Object.entries(options.metadata)) {
        if (value.trim()) {
          pandocCmd += ` -M ${key}="${value.replace(/"/g, '\\"')}"`;
        }
      }
    }

    // Add variables
    if (options.variables) {
      for (const [key, value] of Object.entries(options.variables)) {
        if (value.trim()) {
          pandocCmd += ` -V ${key}="${value.replace(/"/g, '\\"')}"`;
        }
      }
    }

    // Add other options
    if (options.toc) pandocCmd += ' --toc';
    if (options.tocDepth) pandocCmd += ` --toc-depth=${options.tocDepth}`;
    if (options.numberSections) pandocCmd += ' --number-sections';
    if (options.citeproc) pandocCmd += ' --citeproc';
    if (options.bibliography) pandocCmd += ` --bibliography="${options.bibliography}"`;
    if (options.csl) pandocCmd += ` --csl="${options.csl}"`;

    // Add specific options for PDF export to ensure proper generation
    if (format === 'pdf') {
      const pdfEngine = options.pdfEngine || 'xelatex'; // Default to xelatex
      pandocCmd += ` --pdf-engine="${pdfEngine}"`;
      if (options.geometry) pandocCmd += ` -V geometry:"${options.geometry}"`;

      // Add monospace font settings for code blocks (ASCII art preservation)
      pandocCmd += ' -V monofont="Consolas"';
      pandocCmd += ' --highlight-style=tango';

      // Add header/footer if enabled
      if (headerFooterSettings.enabled) {
        const filename = currentFile ? path.basename(currentFile, path.extname(currentFile)) : 'document';
        const metadata = { filename, title: filename, author: '' };

        const headerLeft = processDynamicFields(headerFooterSettings.header.left, metadata);
        const headerCenter = processDynamicFields(headerFooterSettings.header.center, metadata);
        const headerRight = processDynamicFields(headerFooterSettings.header.right, metadata);
        const footerLeft = processDynamicFields(headerFooterSettings.footer.left, metadata);
        const footerCenter = processDynamicFields(headerFooterSettings.footer.center, metadata);
        const footerRight = processDynamicFields(headerFooterSettings.footer.right, metadata);

        // Create LaTeX header
        const latexHeader = `
\\usepackage{fancyhdr}
\\pagestyle{fancy}
\\fancyhf{}
\\lhead{${headerLeft.replace(/\\/g, '\\\\')}}
\\chead{${headerCenter.replace(/\\/g, '\\\\')}}
\\rhead{${headerRight.replace(/\\/g, '\\\\')}}
\\lfoot{${footerLeft.replace(/\\/g, '\\\\')}}
\\cfoot{${footerCenter.replace(/[$]PAGE[$]/g, '\\\\thepage').replace(/[$]TOTAL[$]/g, '\\\\pageref{LastPage}').replace(/\\/g, '\\\\')}}
\\rfoot{${footerRight.replace(/\\/g, '\\\\')}}
\\renewcommand{\\headrulewidth}{0.4pt}
\\renewcommand{\\footrulewidth}{0.4pt}
`;
        const headerFile = path.join(require('os').tmpdir(), `header_export_${Date.now()}.tex`);
        fs.writeFileSync(headerFile, latexHeader, 'utf-8');
        pandocCmd += ` --include-in-header="${headerFile}"`;
        pandocCmd += ' --variable header-includes="\\\\usepackage{lastpage}"';
      }

      // Try with specified PDF engine (using runPandocCmd for safety)
      runPandocCmd(pandocCmd, (error) => {
        if (error) {
          // Try fallback engines if the specified one fails
          const fallbackEngines = ['pdflatex', 'lualatex'];
          tryPdfFallback(currentFile, outputFile, fallbackEngines, 0, options, error);
        } else {
          showExportSuccess(outputFile);
        }
      });
    } else if (format === 'docx') {
      pandocCmd += ' -t docx';
      exportWithPandoc(pandocCmd, outputFile, format);
    } else if (format === 'pptx') {
      // Add PowerPoint footer if enabled
      if (headerFooterSettings.enabled && headerFooterSettings.footer.center) {
        const filename = currentFile ? path.basename(currentFile, path.extname(currentFile)) : 'document';
        const metadata = { filename, title: filename, author: '' };
        const footerText = processDynamicFields(headerFooterSettings.footer.center, metadata);
        pandocCmd += ` --variable footer="${footerText}"`;
      }
      exportWithPandoc(pandocCmd, outputFile, format);
    } else if (format === 'json') {
      pandocCmd = `${getPandocPath()} "${currentFile}" -t json -o "${outputFile}"`;
      exportWithPandoc(pandocCmd, outputFile, format);
    } else if (format === 'yaml' || format === 'xml' || format === 'toml') {
      // For YAML/XML/TOML, save the raw markdown content with the new extension
      try {
        const content = fs.readFileSync(currentFile, 'utf-8');
        fs.writeFileSync(outputFile, content, 'utf-8');
        showExportSuccess(outputFile);
      } catch (err) {
        dialog.showErrorBox('Export Error', sanitizeErrorMessage(`Failed to export: ${err.message}`));
      }
    } else if (format === 'revealjs') {
      let revealCmd = `${getPandocPath()} "${currentFile}" -t revealjs -s -o "${outputFile}" --slide-level=2`;
      if (options) {
        if (options.revealTheme) revealCmd += ` -V theme="${options.revealTheme}"`;
        if (options.revealTransition) revealCmd += ` -V transition="${options.revealTransition}"`;
        if (options.revealTransitionSpeed) revealCmd += ` -V transitionSpeed="${options.revealTransitionSpeed}"`;
        if (options.revealControls !== undefined) revealCmd += ` -V controls="${options.revealControls}"`;
        if (options.revealSlideNumber !== undefined) revealCmd += ` -V slideNumber="${options.revealSlideNumber}"`;
        if (options.revealProgress !== undefined) revealCmd += ` -V progress="${options.revealProgress}"`;
        if (options.revealHistory !== undefined) revealCmd += ` -V history="${options.revealHistory}"`;
        if (options.revealCenter !== undefined) revealCmd += ` -V center="${options.revealCenter}"`;

        // Support for templates, metadata, bibliography
        if (options.template && options.template !== 'default') {
          revealCmd += ` --template="${options.template}"`;
        }
        if (options.metadata) {
          for (const [key, value] of Object.entries(options.metadata)) {
            if (value.trim()) {
              revealCmd += ` -M ${key}="${value.replace(/"/g, '\\"')}"`;
            }
          }
        }
        if (options.bibliography) revealCmd += ` --bibliography="${options.bibliography}"`;
        if (options.csl) revealCmd += ` --csl="${options.csl}"`;
      }
      exportWithPandoc(revealCmd, outputFile, format);
    } else if (format === 'beamer') {
      pandocCmd = `${getPandocPath()} "${currentFile}" -t beamer -o "${outputFile}"`;
      exportWithPandoc(pandocCmd, outputFile, format);
    } else if (format === 'confluence' || format === 'jira') {
      pandocCmd = `${getPandocPath()} "${currentFile}" -t jira -o "${outputFile}"`;
      exportWithPandoc(pandocCmd, outputFile, format);
    } else if (format === 'mobi') {
      // First export to EPUB, then try ebook-convert if available
      const epubFile = outputFile.replace(/\.mobi$/i, '.epub');
      pandocCmd = `${getPandocPath()} "${currentFile}" -o "${epubFile}"`;
      runPandocCmd(pandocCmd, (error) => {
        if (error) {
          dialog.showErrorBox('Export Error', sanitizeErrorMessage(`Failed to export EPUB intermediate: ${error.message}`));
          return;
        }
        // Try ebook-convert (Calibre) for MOBI
        execFile('ebook-convert', [epubFile, outputFile], (ebookError) => {
          if (ebookError) {
            dialog.showMessageBox(mainWindow, {
              type: 'warning',
              title: 'MOBI Export - Partial',
              message: `Calibre's ebook-convert was not found. The file has been exported as EPUB instead.\n\nEPUB saved to: ${epubFile}\n\nTo get MOBI output, install Calibre from: https://calibre-ebook.com/`,
              buttons: ['OK']
            });
          } else {
            // Clean up intermediate EPUB
            try { fs.unlinkSync(epubFile); } catch (e) { /* ignore */ }
            showExportSuccess(outputFile);
          }
        });
      });
    } else {
      // Generic export for other formats
      exportWithPandoc(pandocCmd, outputFile, format);
    }
  }).catch((error) => {
    console.error('Error checking pandoc availability:', error);
    dialog.showErrorBox('Export Error', sanitizeErrorMessage(`Error checking system requirements: ${error.message}`));
  });
}

function tryPdfFallback(inputFile, outputFile, engines, index, options, lastError) {
  if (index >= engines.length) {
    // All Pandoc PDF engines failed, fallback to Electron's built-in PDF export
    console.log('All Pandoc PDF engines failed, falling back to Electron PDF export');
    exportToPDFElectron(outputFile);
    return;
  }

  const engine = engines[index];
  let pandocCmd = `${getPandocPath()} "${inputFile}" --pdf-engine=${engine} -o "${outputFile}"`;

  // Add monospace font settings for code blocks (ASCII art preservation)
  pandocCmd += ' -V monofont="Consolas"';
  pandocCmd += ' --highlight-style=tango';

  // Add geometry if specified
  if (options.geometry) pandocCmd = pandocCmd.replace(` -o `, ` -V geometry:"${options.geometry}" -o `);

  // Add header/footer if enabled
  if (headerFooterSettings.enabled) {
    const filename = path.basename(inputFile, path.extname(inputFile));
    const metadata = { filename, title: filename, author: options.metadata?.author || '' };

    const headerLeft = processDynamicFields(headerFooterSettings.header.left, metadata);
    const headerCenter = processDynamicFields(headerFooterSettings.header.center, metadata);
    const headerRight = processDynamicFields(headerFooterSettings.header.right, metadata);
    const footerLeft = processDynamicFields(headerFooterSettings.footer.left, metadata);
    const footerCenter = processDynamicFields(headerFooterSettings.footer.center, metadata);
    const footerRight = processDynamicFields(headerFooterSettings.footer.right, metadata);

    // Create LaTeX header for fancyhdr
    const latexHeader = `
\\usepackage{fancyhdr}
\\usepackage{lastpage}
\\pagestyle{fancy}
\\fancyhf{}
\\lhead{${headerLeft.replace(/\\/g, '\\\\')}}
\\chead{${headerCenter.replace(/\\/g, '\\\\')}}
\\rhead{${headerRight.replace(/\\/g, '\\\\')}}
\\lfoot{${footerLeft.replace(/\\/g, '\\\\')}}
\\cfoot{${footerCenter.replace(/\$PAGE\$/g, '\\\\thepage').replace(/\$TOTAL\$/g, '\\\\pageref{LastPage}').replace(/\\/g, '\\\\')}}
\\rfoot{${footerRight.replace(/\\/g, '\\\\')}}
\\renewcommand{\\headrulewidth}{0.4pt}
\\renewcommand{\\footrulewidth}{0.4pt}
`;
    const headerFile = path.join(require('os').tmpdir(), `header_fallback_${Date.now()}.tex`);
    fs.writeFileSync(headerFile, latexHeader, 'utf-8');
    pandocCmd += ` --include-in-header="${headerFile}"`;
  }

  // Add all other options
  if (options.template && options.template !== 'default') {
    pandocCmd += ` --template="${options.template}"`;
  }

  if (options.metadata) {
    for (const [key, value] of Object.entries(options.metadata)) {
      if (value.trim()) {
        pandocCmd += ` -M ${key}="${value.replace(/"/g, '\\"')}"`;
      }
    }
  }

  // Use runPandocCmd for safety (prevents command injection)
  runPandocCmd(pandocCmd, (error) => {
    if (error) {
      tryPdfFallback(inputFile, outputFile, engines, index + 1, options, error);
    } else {
      showExportSuccess(outputFile);
    }
  });
}

function showExportSuccess(outputFile) {
  dialog.showMessageBox(mainWindow, {
    type: 'info',
    title: 'Export Complete',
    message: `File exported successfully to ${outputFile}`,
    buttons: ['OK']
  });
}

// Helper function to export with pandoc (general) - uses runPandocCmd for safety
function exportWithPandoc(pandocCmd, outputFile, format) {
  console.log(`Executing Pandoc command: ${pandocCmd}`);

  runPandocCmd(pandocCmd, async (error, stdout, stderr) => {
    if (error) {
      console.error(`Pandoc error for ${format}:`, error);
      console.error(`Pandoc stderr:`, stderr);
      console.error(`Pandoc stdout:`, stdout);

      // Provide more specific error messages
      let errorMessage = `Failed to export to ${format.toUpperCase()}`;

      if (error.message.includes('not found') || error.message.includes('not recognized')) {
        errorMessage += '\n\nPandoc is not installed or not found in PATH.';
        errorMessage += '\nPlease install Pandoc from: https://pandoc.org/installing.html';
      } else if (stderr) {
        errorMessage += `\n\nError details: ${stderr}`;
      } else {
        errorMessage += `\n\nError details: ${error.message}`;
      }

      errorMessage += `\n\nCommand used: ${pandocCmd}`;

      dialog.showErrorBox('Export Error', sanitizeErrorMessage(errorMessage));
    } else {
      console.log(`Successfully exported to ${format}:`, outputFile);
      console.log(`Pandoc stdout:`, stdout);
      if (stderr) {
        console.warn(`Pandoc stderr (non-fatal):`, stderr);
      }

      // Set page size for DOCX
      if (format === 'docx') {
        try {
          await setDocxPageSize(outputFile);
          console.log('Page size set for DOCX');
        } catch (pageSizeError) {
          console.error('Error setting page size for DOCX:', pageSizeError);
        }
      }

      // Add headers/footers to DOCX if enabled
      if (format === 'docx' && headerFooterSettings.enabled) {
        try {
          const filename = currentFile ? path.basename(currentFile, path.extname(currentFile)) : 'document';
          const metadata = {
            filename: filename,
            title: filename,
            author: ''
          };
          await addHeaderFooterToDocx(outputFile, metadata);
          console.log('Headers/footers added to DOCX');
        } catch (hfError) {
          console.error('Error adding headers/footers to DOCX:', hfError);
          // Continue with success message even if header/footer fails
        }
      }

      // Set page size for ODT
      if (format === 'odt') {
        try {
          await setDocxPageSize(outputFile); // ODT has similar structure
          console.log('Page size set for ODT');
        } catch (pageSizeError) {
          console.error('Error setting page size for ODT:', pageSizeError);
        }
      }

      // Add headers/footers to ODT if enabled
      if (format === 'odt' && headerFooterSettings.enabled) {
        // ODT format is similar to DOCX in structure, we could implement this
        console.log('ODT header/footer support not yet implemented');
      }

      showExportSuccess(outputFile);
    }
  });
}

// Helper function to export PDF with pandoc (with fallbacks) - uses runPandocCmd for safety
function exportWithPandocPDF(pandocCmd, outputFile) {
  runPandocCmd(pandocCmd, (error, stdout, stderr) => {
    if (error) {
      console.log('XeLaTeX failed, trying PDFLaTeX...');
      // Fallback to pdflatex
      const fallbackCmd = pandocCmd.replace('--pdf-engine=xelatex', '--pdf-engine=pdflatex');
      runPandocCmd(fallbackCmd, (fallbackError, fallbackStdout, fallbackStderr) => {
        if (fallbackError) {
          console.log('PDFLaTeX failed, trying Electron PDF...');
          // Final fallback to Electron PDF
          exportToPDFElectron(outputFile);
        } else {
          console.log('Successfully exported PDF with PDFLaTeX');
          showExportSuccess(outputFile);
        }
      });
    } else {
      console.log('Successfully exported PDF with XeLaTeX');
      showExportSuccess(outputFile);
    }
  });
}

// Export to HTML using marked (no pandoc required)
function exportToHTML(outputFile) {
  try {
    const marked = require('marked');
    const markdownContent = fs.readFileSync(currentFile, 'utf8');
    const htmlContent = marked.parse(markdownContent);

    const fullHtml = `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Exported Document</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 800px;
            margin: 0 auto;
            padding: 40px;
        }
        h1, h2, h3, h4, h5, h6 {
            margin-top: 1.5em;
            margin-bottom: 0.5em;
        }
        /* Inline code */
        code {
            background: #f4f4f4;
            padding: 2px 4px;
            border-radius: 3px;
            font-family: Consolas, Monaco, 'Courier New', monospace;
            font-size: 0.9em;
        }
        /* Code blocks - critical for ASCII art preservation */
        pre {
            background: #f5f5f5;
            padding: 1em;
            border-radius: 5px;
            overflow-x: auto;
            white-space: pre;
            word-wrap: normal;
            font-family: Consolas, Monaco, 'Courier New', monospace;
            font-size: 13px;
            line-height: 1.4;
            border: 1px solid #e0e0e0;
            margin: 1em 0;
        }
        pre code {
            background: transparent;
            padding: 0;
            font-family: inherit;
            font-size: inherit;
            line-height: inherit;
            white-space: pre;
            word-wrap: normal;
            display: block;
        }
        blockquote {
            border-left: 4px solid #ddd;
            margin-left: 0;
            padding-left: 1em;
            color: #666;
        }
        table {
            border-collapse: collapse;
            width: 100%;
            margin: 1em 0;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f4f4f4;
        }
        a {
            color: #0066cc;
            text-decoration: none;
        }
        a:hover {
            text-decoration: underline;
        }
        img {
            max-width: 100%;
            height: auto;
        }
        @media print {
            pre {
                white-space: pre;
                word-wrap: normal;
                overflow: visible;
                page-break-inside: avoid;
            }
            pre code {
                white-space: pre;
                word-wrap: normal;
            }
        }
    </style>
</head>
<body>
    ${htmlContent}
</body>
</html>`;

    fs.writeFileSync(outputFile, fullHtml, 'utf8');
    console.log('Successfully exported HTML');
    showExportSuccess(outputFile);
  } catch (error) {
    console.error('HTML export error:', error);
    dialog.showErrorBox('HTML Export Error', sanitizeErrorMessage(`Failed to export HTML: ${error.message}`));
  }
}

// Export to PDF using Electron (no pandoc required)
function exportToPDFElectron(outputFile) {
  try {
    const marked = require('marked');
    const markdownContent = fs.readFileSync(currentFile, 'utf8');
    const htmlContent = marked.parse(markdownContent);

    const fullHtml = `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PDF Export</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 800px;
            margin: 0 auto;
            padding: 40px;
        }
        h1, h2, h3, h4, h5, h6 {
            margin-top: 1.5em;
            margin-bottom: 0.5em;
        }
        /* Inline code */
        code {
            background: #f4f4f4;
            padding: 2px 4px;
            border-radius: 3px;
            font-family: Consolas, Monaco, 'Courier New', monospace;
            font-size: 0.9em;
        }
        /* Code blocks - critical for ASCII art preservation */
        pre {
            background: #f5f5f5;
            padding: 1em;
            border-radius: 5px;
            overflow-x: visible;
            overflow-y: visible;
            white-space: pre;
            word-wrap: normal;
            font-family: Consolas, Monaco, 'Courier New', monospace;
            font-size: 12px;
            line-height: 1.4;
            border: 1px solid #e0e0e0;
            margin: 1em 0;
        }
        pre code {
            background: transparent;
            padding: 0;
            font-family: inherit;
            font-size: inherit;
            line-height: inherit;
            white-space: pre;
            word-wrap: normal;
            display: block;
        }
        blockquote {
            border-left: 4px solid #ddd;
            margin-left: 0;
            padding-left: 1em;
            color: #666;
        }
        table {
            border-collapse: collapse;
            width: 100%;
            margin: 1em 0;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f4f4f4;
        }
        img {
            max-width: 100%;
            height: auto;
        }
        @media print {
            body { padding: 20px; }
            pre {
                white-space: pre;
                word-wrap: normal;
                overflow: visible;
                page-break-inside: avoid;
            }
            pre code {
                white-space: pre;
                word-wrap: normal;
            }
        }
    </style>
</head>
<body>
    ${htmlContent}
</body>
</html>`;

    // Create a hidden window to render and export PDF
    const pdfWindow = new BrowserWindow({
      show: false,
      webPreferences: {
        nodeIntegration: true,
        contextIsolation: false
      }
    });
    
    pdfWindow.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(fullHtml)}`).then(() => {
      return pdfWindow.webContents.printToPDF({
        marginsType: 1, // Use default margins
        pageSize: 'A4',
        printBackground: true,
        printSelectionOnly: false,
        landscape: false
      });
    }).then((pdfData) => {
      fs.writeFileSync(outputFile, pdfData);
      pdfWindow.close();
      console.log('Successfully exported PDF with Electron');
      showExportSuccess(outputFile);
    }).catch((error) => {
      pdfWindow.close();
      console.error('Electron PDF export error:', error);
      dialog.showErrorBox('PDF Export Error',
        sanitizeErrorMessage(`Failed to export PDF using built-in engine: ${error.message}\n\n` +
        `For better PDF export, please install Pandoc with LaTeX support.`)
      );
    });
  } catch (error) {
    console.error('PDF export setup error:', error);
    dialog.showErrorBox('PDF Export Error', sanitizeErrorMessage(`Failed to setup PDF export: ${error.message}`));
  }
}

function exportSpreadsheet(format) {
  if (!currentFile) {
    dialog.showErrorBox('Error', 'Please save the file first');
    return;
  }

  // Request content from renderer
  mainWindow.webContents.send('get-content-for-spreadsheet', format);
}

function importDocument() {
  const files = dialog.showOpenDialogSync(mainWindow, {
    properties: ['openFile'],
    filters: [
      { name: 'Documents', extensions: ['docx', 'odt', 'rtf', 'html', 'htm', 'tex', 'epub', 'pdf', 'txt'] },
      { name: 'Presentations', extensions: ['pptx', 'odp'] },
      { name: 'Markup Languages', extensions: ['rst', 'textile', 'mediawiki', 'org', 'asciidoc', 'twiki', 'opml'] },
      { name: 'E-book Formats', extensions: ['epub', 'fb2'] },
      { name: 'LaTeX Formats', extensions: ['tex', 'latex', 'ltx'] },
      { name: 'Web Formats', extensions: ['html', 'htm', 'xhtml'] },
      { name: 'Wiki Formats', extensions: ['mediawiki', 'dokuwiki', 'tikiwiki', 'twiki'] },
      { name: 'CSV/TSV', extensions: ['csv', 'tsv'] },
      { name: 'Developer Formats', extensions: ['json', 'yaml', 'yml', 'xml', 'toml'] },
      { name: 'All Files', extensions: ['*'] }
    ]
  });

  if (files && files[0]) {
    const inputFile = files[0];
    const stats = fs.statSync(inputFile);
    if (stats.size > MAX_FILE_SIZE) {
        dialog.showErrorBox('File Too Large', `File exceeds the ${MAX_FILE_SIZE_MB}MB size limit.`);
        return;
    }
    const ext = path.extname(inputFile).toLowerCase().slice(1);
    const outputFile = inputFile.replace(/\.[^/.]+$/, '.md');

    // Determine format-specific conversion options
    let additionalOptions = '';

    // For PDFs, extract text properly
    if (ext === 'pdf') {
      additionalOptions = '--pdf-engine=xelatex';
    }

    // For CSV/TSV, convert as tables
    if (ext === 'csv' || ext === 'tsv') {
      additionalOptions = '--from=csv -t markdown';
    }

    // For JSON, handle structure
    if (ext === 'json') {
      additionalOptions = '--from=json -t markdown';
    }

    // For YAML, XML, TOML - wrap content in code blocks directly
    if (['yaml', 'yml', 'xml', 'toml'].includes(ext)) {
      const rawContent = fs.readFileSync(inputFile, 'utf-8');
      const mdContent = convertDataToMarkdown(rawContent, ext);
      const mdOutputFile = inputFile.replace(/\.[^/.]+$/, '.md');
      fs.writeFileSync(mdOutputFile, mdContent, 'utf-8');
      currentFile = mdOutputFile;
      mainWindow.webContents.send('file-opened', { path: mdOutputFile, content: mdContent });
      dialog.showMessageBox(mainWindow, {
        type: 'info',
        title: 'Import Complete',
        message: `Document imported successfully as ${path.basename(mdOutputFile)}\n\nOriginal format: ${ext.toUpperCase()}\nConverted to: Markdown`,
        buttons: ['OK']
      });
      return;
    }

    // Convert to markdown using pandoc (using runPandocCmd for safety)
    const pandocCmd = `${getPandocPath()} "${inputFile}" -t markdown ${additionalOptions} -o "${outputFile}"`;

    runPandocCmd(pandocCmd, (error, stdout, stderr) => {
      if (error) {
        dialog.showErrorBox('Import Error', sanitizeErrorMessage(`Failed to import: ${error.message}\n\nMake sure Pandoc is installed.\n\nSupported formats: DOCX, ODT, RTF, HTML, LaTeX, EPUB, PDF, PPTX, ODP, RST, Textile, MediaWiki, Org-mode, AsciiDoc, CSV, and more.`));
      } else {
        // Open the converted markdown file
        currentFile = outputFile;
        const content = fs.readFileSync(outputFile, 'utf-8');
        mainWindow.webContents.send('file-opened', { path: outputFile, content });

        dialog.showMessageBox(mainWindow, {
          type: 'info',
          title: 'Import Complete',
          message: `Document imported successfully as ${path.basename(outputFile)}\n\nOriginal format: ${ext.toUpperCase()}\nConverted to: Markdown`,
          buttons: ['OK']
        });
      }
    });
  }
}


function setTheme(theme) {
  store.set('theme', theme);
  mainWindow.webContents.send('theme-changed', theme);
}

// IPC handlers
ipcMain.on('save-file', (event, { path, content }) => {
  fs.writeFileSync(path, content, 'utf-8');
  currentFile = path;
});

ipcMain.on('save-current-file', (event, payload) => {
  const content = typeof payload === 'string' ? payload : payload?.content;
  const targetFile = typeof payload === 'string' ? currentFile : payload?.filePath || currentFile;

  if (targetFile) {
    fs.writeFileSync(targetFile, content, 'utf-8');
    currentFile = targetFile;
  } else {
    saveAsFile();
  }
});

ipcMain.on('get-theme', (event) => {
  const theme = store.get('theme', 'atomonelight');
  event.reply('theme-changed', theme);
});

// Handle tab file tracking for exports
ipcMain.on('set-current-file', (event, filePath) => {
  currentFile = filePath;
});

// Handle actual printing when renderer is ready
ipcMain.on('do-print', (event, { withStyles }) => {
  if (mainWindow) {
    // Renderer has already hidden UI, waited 300ms, and prepared the page
    // Print immediately - DOM is fully rendered
    mainWindow.webContents.print({
      silent: false,
      printBackground: withStyles,
      color: true,
      margin: { marginType: 'default' }
    });
  }
});

// Handle printing with custom options from print preview dialog
ipcMain.on('do-print-with-options', (event, options) => {
  if (!mainWindow) return;

  const marginsMap = {
    'default': { marginType: 'default' },
    'narrow': { top: 0.4, bottom: 0.4, left: 0.4, right: 0.4 },
    'wide': { top: 1.0, bottom: 1.0, left: 1.0, right: 1.0 },
    'none': { top: 0, bottom: 0, left: 0, right: 0 },
  };

  const printOptions = {
    silent: false,
    printBackground: options.background,
    landscape: options.orientation === 'landscape',
    scaleFactor: options.scale / 100,
    pageSize: options.paperSize,
  };

  if (options.margins && options.margins !== 'default') {
    printOptions.margins = marginsMap[options.margins];
  }

  mainWindow.webContents.print(printOptions);
});

// Handle renderer ready for file association
ipcMain.on('renderer-ready', (event) => {
  console.log('[MAIN] renderer-ready received, rendererReady was:', rendererReady);
  if (mainWindow) {
    mainWindow.webContents.executeJavaScript(`console.log('[MAIN->RENDERER] renderer-ready received, rendererReady was: ${rendererReady}')`);
  }
  rendererReady = true;
  console.log('[MAIN] app.pendingFile:', app.pendingFile);
  if (mainWindow) {
    mainWindow.webContents.executeJavaScript(`console.log('[MAIN->RENDERER] app.pendingFile: ${app.pendingFile}')`);
  }
  if (app.pendingFile) {
    console.log('[MAIN] Opening pending file:', app.pendingFile);
    if (mainWindow) {
      mainWindow.webContents.executeJavaScript(`console.log('[MAIN->RENDERER] Opening pending file: ${app.pendingFile}')`);
    }
    openFileFromPath(app.pendingFile);
    app.pendingFile = null;
  }
});

// Handle export with options
ipcMain.on('export-with-options', (event, { format, options }) => {
  if (!conversionLimiter()) {
    mainWindow.webContents.send('conversion-status', 'Please wait before converting again...');
    return;
  }
  performExportWithOptions(format, options);
});

// Handle batch conversion
ipcMain.on('batch-convert', (event, { inputFolder, outputFolder, format, options }) => {
  if (!conversionLimiter()) {
    mainWindow.webContents.send('conversion-status', 'Please wait before converting again...');
    return;
  }
  performBatchConversion(inputFolder, outputFolder, format, options);
});

// Handle folder selection for batch conversion
ipcMain.on('select-folder', (event, type) => {
  const folder = dialog.showOpenDialogSync(mainWindow, {
    properties: ['openDirectory']
  });

  if (folder && folder[0]) {
    event.reply('folder-selected', { type, path: folder[0] });
  }
});

// List directory contents as FileEntry[]
ipcMain.handle('list-directory', async (event, dirPath) => {
  try {
    const entries = fs.readdirSync(dirPath, { withFileTypes: true });
    return entries.map((dirent) => {
      const fullPath = path.join(dirPath, dirent.name);
      let size;
      let modifiedAt;
      if (!dirent.isDirectory()) {
        try {
          const stat = fs.statSync(fullPath);
          size = stat.size;
          modifiedAt = stat.mtime.toISOString();
        } catch {
          // ignore stat errors
        }
      }
      return {
        name: dirent.name,
        path: fullPath,
        isDirectory: dirent.isDirectory(),
        size,
        modifiedAt,
      };
    });
  } catch (err) {
    return { error: err.message };
  }
});

// Show folder picker dialog and return selected path or null
ipcMain.handle('pick-folder', async () => {
  const result = await dialog.showOpenDialog(mainWindow, {
    properties: ['openDirectory'],
  });
  if (result.canceled || result.filePaths.length === 0) return null;
  return result.filePaths[0];
});

// Show file picker dialog for markdown files and return selected path or null
ipcMain.handle('pick-file', async () => {
  const result = await dialog.showOpenDialog(mainWindow, {
    properties: ['openFile'],
    filters: [{ name: 'Markdown', extensions: ['md', 'markdown', 'mdown', 'mkd'] }],
  });
  if (result.canceled || result.filePaths.length === 0) return null;
  return result.filePaths[0];
});

ipcMain.on('export-spreadsheet', (event, { content, format }) => {
  const outputFile = dialog.showSaveDialogSync(mainWindow, {
    defaultPath: currentFile.replace(/\.[^/.]+$/, `.${format}`),
    filters: [
      { name: format.toUpperCase(), extensions: [format] }
    ]
  });

  if (outputFile) {
    try {
      // Parse markdown content to extract tables
      const tables = extractTablesFromMarkdown(content);

      if (tables.length === 0) {
        dialog.showErrorBox('Export Error', 'No tables found in the markdown content');
        return;
      }

      if (format === 'csv') {
        // Convert tables to CSV format
        let csvContent = '';
        tables.forEach((table, index) => {
          if (index > 0) csvContent += '\n\n'; // Separate multiple tables
          if (tables.length > 1) csvContent += `"Table ${index + 1}"\n`;

          table.forEach(row => {
            const csvRow = row.map(cell => {
              // Escape quotes and wrap in quotes if necessary
              const cleanCell = cell.replace(/"/g, '""');
              return cleanCell.includes(',') || cleanCell.includes('"') || cleanCell.includes('\n')
                ? `"${cleanCell}"` : cleanCell;
            }).join(',');
            csvContent += csvRow + '\n';
          });
        });

        fs.writeFileSync(outputFile, csvContent, 'utf-8');
      }

      dialog.showMessageBox(mainWindow, {
        type: 'info',
        title: 'Export Complete',
        message: `${format.toUpperCase()} exported successfully to ${outputFile}`,
        buttons: ['OK']
      });
    } catch (error) {
      dialog.showErrorBox('Export Error', sanitizeErrorMessage(`Failed to export: ${error.message}`));
    }
  }
});

// Helper function to extract tables from markdown
function extractTablesFromMarkdown(markdown) {
  const tables = [];
  const lines = markdown.split('\n');
  let currentTable = [];
  let inTable = false;
  
  for (const line of lines) {
    if (line.includes('|')) {
      if (!inTable) {
        inTable = true;
        currentTable = [];
      }
      
      // Skip separator lines (|---|---|)
      if (!line.match(/^\s*\|?\s*:?-+:?\s*\|/)) {
        const cells = line.split('|')
          .map(cell => cell.trim())
          .filter(cell => cell !== '');
        
        if (cells.length > 0) {
          currentTable.push(cells);
        }
      }
    } else if (inTable && line.trim() === '') {
      // End of table
      if (currentTable.length > 0) {
        tables.push(currentTable);
      }
      currentTable = [];
      inTable = false;
    }
  }
  
  // Add last table if exists
  if (currentTable.length > 0) {
    tables.push(currentTable);
  }
  
  return tables;
}

function performBatchConversion(inputFolder, outputFolder, format, options) {
  if (!fs.existsSync(inputFolder)) {
    dialog.showErrorBox('Error', 'Input folder does not exist');
    return;
  }

  // Create output folder if it doesn't exist
  if (!fs.existsSync(outputFolder)) {
    try {
      fs.mkdirSync(outputFolder, { recursive: true });
    } catch (error) {
      dialog.showErrorBox('Error', sanitizeErrorMessage(`Failed to create output folder: ${error.message}`));
      return;
    }
  }

  // Find all markdown files in input folder
  const markdownFiles = [];

  function findMarkdownFiles(dir) {
    const files = fs.readdirSync(dir);

    for (const file of files) {
      const fullPath = path.join(dir, file);
      const stat = fs.statSync(fullPath);

      if (stat.isDirectory()) {
        findMarkdownFiles(fullPath); // Recursive search
      } else if (file.match(/\.(md|markdown)$/i)) {
        markdownFiles.push(fullPath);
      }
    }
  }

  findMarkdownFiles(inputFolder);

  if (markdownFiles.length === 0) {
    dialog.showErrorBox('No Files Found', 'No markdown files found in the selected folder');
    return;
  }

  // Show progress dialog
  let completedCount = 0;
  const totalCount = markdownFiles.length;

  // Process each file
  const processNextFile = async (index) => {
    if (index >= markdownFiles.length) {
      // All files processed
      dialog.showMessageBox(mainWindow, {
        type: 'info',
        title: 'Batch Conversion Complete',
        message: `Successfully converted ${completedCount} out of ${totalCount} files to ${format.toUpperCase()}.`,
        buttons: ['OK']
      });
      return;
    }

    const inputFile = markdownFiles[index];
    const relativePath = path.relative(inputFolder, inputFile);
    const baseName = path.basename(relativePath, path.extname(relativePath));
    let outputExtension = format;
    if (format === 'docx-enhanced') outputExtension = 'docx';
    if (format === 'pdf-enhanced') outputExtension = 'pdf';
    const outputFile = path.join(outputFolder, relativePath.replace(/\.(md|markdown)$/i, `.${outputExtension}`));

    // Create subdirectories in output folder if needed
    const outputDir = path.dirname(outputFile);
    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir, { recursive: true });
    }

    // Handle DOCX Enhanced format with WordTemplateExporter
    if (format === 'docx-enhanced') {
      try {
        const content = fs.readFileSync(inputFile, 'utf-8');
        const exporter = new WordTemplateExporter(wordTemplatePath, templateStartPage);
        await exporter.convert(content, outputFile);

        completedCount++;

        // Update progress
        mainWindow.webContents.send('batch-progress', {
          completed: index + 1,
          total: totalCount,
          currentFile: path.basename(inputFile),
          success: true
        });

        // Process next file
        processNextFile(index + 1);
      } catch (error) {
        // Update progress with error
        mainWindow.webContents.send('batch-progress', {
          completed: index + 1,
          total: totalCount,
          currentFile: path.basename(inputFile),
          success: false
        });

        // Process next file even if this one failed
        processNextFile(index + 1);
      }
      return;
    }

    // Handle PDF Enhanced format with Word Template → PDF conversion
    if (format === 'pdf-enhanced') {
      try {
        const content = fs.readFileSync(inputFile, 'utf-8');

        // Step 1: Create temporary DOCX file using Word template
        const tempDocxPath = outputFile.replace(/\.pdf$/, '_temp.docx');
        const exporter = new WordTemplateExporter(wordTemplatePath, templateStartPage);
        await exporter.convert(content, tempDocxPath);

        // Step 2: Convert DOCX to PDF using LibreOffice (using execFile for safety)
        const soffice = process.platform === 'win32'
          ? 'C:\\Program Files\\LibreOffice\\program\\soffice.exe'
          : 'soffice';

        const outputDir = path.dirname(outputFile);
        const sofficeArgs = ['--headless', '--convert-to', 'pdf', '--outdir', outputDir, tempDocxPath];

        execFile(soffice, sofficeArgs, (error, stdout, stderr) => {
          // Clean up temporary DOCX file
          try {
            fs.unlinkSync(tempDocxPath);
          } catch (e) {
            console.error('Failed to delete temp file:', e);
          }

          if (error) {
            // Update progress with error
            mainWindow.webContents.send('batch-progress', {
              completed: index + 1,
              total: totalCount,
              currentFile: path.basename(inputFile),
              success: false
            });
            processNextFile(index + 1);
            return;
          }

          // LibreOffice creates file with same base name as input
          const generatedPdfPath = tempDocxPath.replace(/\.docx$/, '.pdf');

          // Rename if needed
          if (generatedPdfPath !== outputFile) {
            try {
              fs.renameSync(generatedPdfPath, outputFile);
            } catch (e) {
              console.error('Failed to rename PDF:', e);
            }
          }

          completedCount++;

          // Update progress
          mainWindow.webContents.send('batch-progress', {
            completed: index + 1,
            total: totalCount,
            currentFile: path.basename(inputFile),
            success: true
          });

          // Process next file
          processNextFile(index + 1);
        });

      } catch (error) {
        // Update progress with error
        mainWindow.webContents.send('batch-progress', {
          completed: index + 1,
          total: totalCount,
          currentFile: path.basename(inputFile),
          success: false
        });

        // Process next file even if this one failed
        processNextFile(index + 1);
      }
      return;
    }

    // Build pandoc command for other formats
    let pandocCmd = `${getPandocPath()} "${inputFile}" -o "${outputFile}"`;

    // Add template if specified
    if (options.template && options.template !== 'default') {
      pandocCmd += ` --template="${options.template}"`;
    }

    // Add metadata
    if (options.metadata) {
      for (const [key, value] of Object.entries(options.metadata)) {
        if (value.trim()) {
          pandocCmd += ` -M ${key}="${value.replace(/"/g, '\\"')}"`;
        }
      }
    }

    // Add variables
    if (options.variables) {
      for (const [key, value] of Object.entries(options.variables)) {
        if (value.trim()) {
          pandocCmd += ` -V ${key}="${value.replace(/"/g, '\\"')}"`;
        }
      }
    }

    // Add other options
    if (options.toc) pandocCmd += ' --toc';
    if (options.tocDepth) pandocCmd += ` --toc-depth=${options.tocDepth}`;
    if (options.numberSections) pandocCmd += ' --number-sections';
    if (options.citeproc) pandocCmd += ' --citeproc';
    if (options.bibliography) pandocCmd += ` --bibliography="${options.bibliography}"`;
    if (options.csl) pandocCmd += ` --csl="${options.csl}"`;

    // Add PDF-specific options with header/footer support
    if (format === 'pdf') {
      const pdfEngine = options.pdfEngine || 'xelatex';
      pandocCmd += ` --pdf-engine=${pdfEngine}`;
      if (options.geometry) pandocCmd += ` -V geometry:"${options.geometry}"`;

      // Add monospace font settings for code blocks (ASCII art preservation)
      pandocCmd += ' -V monofont="Consolas"';
      pandocCmd += ' --highlight-style=tango';

      // Add header/footer if enabled
      if (headerFooterSettings.enabled) {
        const filename = path.basename(inputFile, path.extname(inputFile));
        const metadata = { filename, title: filename, author: '' };

        const headerLeft = processDynamicFields(headerFooterSettings.header.left, metadata);
        const headerCenter = processDynamicFields(headerFooterSettings.header.center, metadata);
        const headerRight = processDynamicFields(headerFooterSettings.header.right, metadata);
        const footerLeft = processDynamicFields(headerFooterSettings.footer.left, metadata);
        const footerCenter = processDynamicFields(headerFooterSettings.footer.center, metadata);
        const footerRight = processDynamicFields(headerFooterSettings.footer.right, metadata);

        // Create LaTeX header
        const latexHeader = `
\\usepackage{fancyhdr}
\\pagestyle{fancy}
\\fancyhf{}
\\lhead{${headerLeft.replace(/\\/g, '\\\\')}}
\\chead{${headerCenter.replace(/\\/g, '\\\\')}}
\\rhead{${headerRight.replace(/\\/g, '\\\\')}}
\\lfoot{${footerLeft.replace(/\\/g, '\\\\')}}
\\cfoot{${footerCenter.replace(/[$]PAGE[$]/g, '\\\\thepage').replace(/[$]TOTAL[$]/g, '\\\\pageref{LastPage}').replace(/\\/g, '\\\\')}}
\\rfoot{${footerRight.replace(/\\/g, '\\\\')}}
\\renewcommand{\\headrulewidth}{0.4pt}
\\renewcommand{\\footrulewidth}{0.4pt}
`;
        const headerFile = path.join(require('os').tmpdir(), `header_batch_${Date.now()}.tex`);
        fs.writeFileSync(headerFile, latexHeader, 'utf-8');
        pandocCmd += ` --include-in-header="${headerFile}"`;
        pandocCmd += ' --variable header-includes="\\\\usepackage{lastpage}"';
      }
    }

    // Add DOCX-specific handling
    if (format === 'docx') {
      pandocCmd += ' -t docx';
    }

    // Add PowerPoint footer if enabled
    if (format === 'pptx' && headerFooterSettings.enabled && headerFooterSettings.footer.center) {
      const filename = path.basename(inputFile, path.extname(inputFile));
      const metadata = { filename, title: filename, author: '' };
      const footerText = processDynamicFields(headerFooterSettings.footer.center, metadata);
      pandocCmd += ` --variable footer="${footerText}"`;
    }

    // Execute conversion (using runPandocCmd for safety)
    runPandocCmd(pandocCmd, async (error, stdout, stderr) => {
      if (!error) {
        // Add headers/footers to DOCX if enabled
        if (format === 'docx' && headerFooterSettings.enabled) {
          try {
            const filename = path.basename(inputFile, path.extname(inputFile));
            const metadata = { filename, title: filename, author: '' };
            await addHeaderFooterToDocx(outputFile, metadata);
          } catch (hfError) {
            console.error('Batch: Error adding headers/footers to DOCX:', hfError);
          }
        }
        completedCount++;
      }

      // Update progress (you could send this to renderer for a progress bar)
      mainWindow.webContents.send('batch-progress', {
        completed: index + 1,
        total: totalCount,
        currentFile: path.basename(inputFile),
        success: !error
      });

      // Process next file
      processNextFile(index + 1);
    });
  };

  // Start processing
  processNextFile(0);
}

// Handle command line interface for file conversion
function handleCLIConversion(args) {
  const command = args[0];
  const filePath = args[args.length - 1]; // File path is always last argument
  
  if (!fs.existsSync(filePath)) {
    console.error(`Error: File not found: ${filePath}`);
    app.quit();
    return;
  }

  // Show conversion dialog for --convert command
  if (command === '--convert') {
    showConversionDialog(filePath);
    return;
  }

  // Direct conversion for --convert-to command
  if (command === '--convert-to' && args.length >= 3) {
    const format = args[1];
    performCLIConversion(filePath, format);
    return;
  }

  console.error('Usage: --convert <file> OR --convert-to <format> <file>');
  app.quit();
}

// Show conversion dialog for CLI
function showConversionDialog(filePath) {
  const { dialog } = require('electron');
  
  // Create a hidden window for dialog operations
  const hiddenWindow = new BrowserWindow({
    show: false,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  const formats = [
    { name: 'PDF', value: 'pdf' },
    { name: 'HTML', value: 'html' },
    { name: 'DOCX', value: 'docx' },
    { name: 'LaTeX', value: 'latex' },
    { name: 'RTF', value: 'rtf' },
    { name: 'ODT', value: 'odt' },
    { name: 'PowerPoint', value: 'pptx' }
  ];

  // Create format selection dialog using message box
  const formatButtons = formats.map(f => f.name);
  formatButtons.push('Cancel');

  dialog.showMessageBox(hiddenWindow, {
    type: 'question',
    title: 'PanConverter - Choose Format',
    message: `Convert "${path.basename(filePath)}" to:`,
    detail: 'Select the output format for conversion',
    buttons: formatButtons,
    defaultId: 0,
    cancelId: formatButtons.length - 1
  }).then(result => {
    if (result.response < formats.length) {
      const selectedFormat = formats[result.response].value;
      performCLIConversion(filePath, selectedFormat);
    } else {
      console.log('Conversion cancelled');
      app.quit();
    }
    hiddenWindow.destroy();
  });
}

// Perform CLI conversion
function performCLIConversion(inputPath, format) {
  try {
    const content = fs.readFileSync(inputPath, 'utf-8');
    const outputPath = inputPath.replace(/\.[^/.]+$/, `.${format}`);
    
    console.log(`Converting "${path.basename(inputPath)}" to ${format.toUpperCase()}...`);
    
    // Use existing export functions but with CLI output (using runPandocCmd for safety)
    const pandocCommand = buildPandocCommand(content, format, outputPath);

    runPandocCmd(pandocCommand, (error, stdout, stderr) => {
      if (error) {
        console.error(`Conversion failed: ${error.message}`);
        if (stderr) console.error(`Details: ${stderr}`);
        app.quit();
        return;
      }

      console.log(`Successfully converted to: ${outputPath}`);

      // Show Windows notification (using exec for PowerShell is acceptable here - hardcoded command)
      if (process.platform === 'win32') {
        const iconPath = path.join(__dirname, '../assets/icon.png');
        execFile('powershell', ['-Command', `New-BurntToastNotification -Text 'PanConverter', 'File converted to ${format.toUpperCase()}' -AppLogo '${iconPath}'`], () => {});
      }

      app.quit();
    });
  } catch (error) {
    console.error(`Error reading file: ${error.message}`);
    app.quit();
  }
}

// Build Pandoc command for CLI conversion
function buildPandocCommand(content, format, outputPath) {
  const inputFile = path.join(require('os').tmpdir(), `panconverter_temp_${Date.now()}.md`);
  fs.writeFileSync(inputFile, content, 'utf-8');

  let command = `pandoc "${inputFile}" -o "${outputPath}"`;

  // Get metadata for dynamic fields
  const filename = currentFile ? path.basename(currentFile, path.extname(currentFile)) : 'document';
  const metadata = {
    filename: filename,
    title: filename,
    author: '',
  };

  switch (format) {
    case 'pdf':
      command += ' --pdf-engine=xelatex --variable geometry:margin=1in';

      // Add page size and orientation
      const pageSize = PAGE_SIZES[pageSettings.size];
      if (pageSize) {
        command += ` -V geometry:papersize=${pageSize.pandoc}`;
      } else if (pageSettings.customWidth && pageSettings.customHeight) {
        // Custom page size
        command += ` -V geometry:paperwidth=${pageSettings.customWidth}`;
        command += ` -V geometry:paperheight=${pageSettings.customHeight}`;
      }

      // Add orientation
      if (pageSettings.orientation === 'landscape') {
        command += ' -V geometry:landscape';
      }

      // Add monospace font settings for code blocks (ASCII art preservation)
      command += ' -V monofont="Consolas"';
      command += ' --highlight-style=tango';

      // Add header/footer if enabled
      if (headerFooterSettings.enabled) {
        // Process dynamic fields
        const headerLeft = processDynamicFields(headerFooterSettings.header.left, metadata);
        const headerCenter = processDynamicFields(headerFooterSettings.header.center, metadata);
        const headerRight = processDynamicFields(headerFooterSettings.header.right, metadata);
        const footerLeft = processDynamicFields(headerFooterSettings.footer.left, metadata);
        const footerCenter = processDynamicFields(headerFooterSettings.footer.center, metadata);
        const footerRight = processDynamicFields(headerFooterSettings.footer.right, metadata);

        // Add Pandoc variables for fancyhdr package
        if (headerLeft) command += ` --variable header-left="${headerLeft}"`;
        if (headerCenter) command += ` --variable header-center="${headerCenter}"`;
        if (headerRight) command += ` --variable header-right="${headerRight}"`;
        if (footerLeft) command += ` --variable footer-left="${footerLeft}"`;
        if (footerCenter) command += ` --variable footer-center="${footerCenter}"`;
        if (footerRight) command += ` --variable footer-right="${footerRight}"`;

        // Create custom LaTeX header with fancyhdr
        const latexHeader = `
\\usepackage{fancyhdr}
\\pagestyle{fancy}
\\fancyhf{}
\\lhead{${headerLeft.replace(/\\/g, '\\\\')}}
\\chead{${headerCenter.replace(/\\/g, '\\\\')}}
\\rhead{${headerRight.replace(/\\/g, '\\\\')}}
\\lfoot{${footerLeft.replace(/\\/g, '\\\\')}}
\\cfoot{${footerCenter.replace(/[$]PAGE[$]/g, '\\\\thepage').replace(/[$]TOTAL[$]/g, '\\\\pageref{LastPage}').replace(/\\/g, '\\\\')}}
\\rfoot{${footerRight.replace(/\\/g, '\\\\')}}
\\renewcommand{\\headrulewidth}{0.4pt}
\\renewcommand{\\footrulewidth}{0.4pt}
`;
        const headerFile = path.join(require('os').tmpdir(), `header_${Date.now()}.tex`);
        fs.writeFileSync(headerFile, latexHeader, 'utf-8');
        command += ` --include-in-header="${headerFile}"`;

        // Add lastpage package for $TOTAL$ support
        command += ' --variable header-includes="\\\\usepackage{lastpage}"';
      }
      break;

    case 'html':
      command += ' --self-contained --css';
      break;

    case 'docx':
      command += ' --reference-doc';

      // For DOCX, header/footer are handled via reference document or separate processing
      // We'll add a note that DOCX headers/footers require reference doc or post-processing
      break;

    case 'odt':
      // ODT headers/footers are handled via reference document
      break;

    case 'latex':
      command += ' --standalone';
      break;

    case 'pptx':
      command += ' --slide-level=2';
      // PowerPoint footer can be added with --variable
      if (headerFooterSettings.enabled && headerFooterSettings.footer.center) {
        const footerText = processDynamicFields(headerFooterSettings.footer.center, metadata);
        command += ` --variable footer="${footerText}"`;
      }
      break;

    case 'json':
      command = `pandoc "${inputFile}" -t json -o "${outputPath}"`;
      break;

    case 'yaml':
      command = `pandoc "${inputFile}" -t markdown -o "${outputPath}"`;
      break;

    case 'xml':
      command = `pandoc "${inputFile}" -t jats -o "${outputPath}"`;
      break;

    case 'toml':
      // TOML: save raw markdown content with .toml extension
      command = `pandoc "${inputFile}" -t markdown -o "${outputPath}"`;
      break;

    case 'revealjs':
      command = `pandoc "${inputFile}" -t revealjs -s -o "${outputPath}" --slide-level=2`;
      break;

    case 'beamer':
      command = `pandoc "${inputFile}" -t beamer -o "${outputPath}"`;
      break;

    case 'confluence':
    case 'jira':
      command = `pandoc "${inputFile}" -t jira -o "${outputPath}"`;
      break;
  }

  return command;
}

app.whenReady().then(() => {
  // Load saved Word template path and settings
  wordTemplatePath = store.get('wordTemplatePath', null);
  templateStartPage = store.get('templateStartPage', 3);

  // Load header/footer settings
  const savedHFSettings = store.get('headerFooterSettings', null);
  if (savedHFSettings) {
    headerFooterSettings = savedHFSettings;
  }

  // Load page size settings
  const savedPageSettings = store.get('pageSettings', null);
  if (savedPageSettings) {
    pageSettings = savedPageSettings;
  }

  // Check for command line conversion requests
  const args = process.argv.slice(2);
  if (args.length >= 2 && (args[0] === '--convert' || args[0] === '--convert-to')) {
    handleCLIConversion(args);
    return; // Don't create window for CLI operations
  }

  createWindow();
  
  // Handle file association on app startup
  // In packaged apps, process.argv structure is different:
  // Development: ['electron', 'app.js', 'file.md'] - need slice(2)
  // Packaged: ['PanConverter.exe', 'file.md'] - need slice(1)
  // We'll check all arguments after the executable
  console.log('[MAIN] Full command line args:', JSON.stringify(process.argv));
  console.log('[MAIN] App is packaged:', app.isPackaged);

  // Start from index 1 (skip executable) and check each argument
  const startIndex = app.isPackaged ? 1 : 2;
  const fileArgs = process.argv.slice(startIndex);
  console.log('[MAIN] File args to process (starting from index', startIndex + '):', fileArgs);

  for (const arg of fileArgs) {
    console.log('[MAIN] Checking arg:', arg);
    if ((arg.endsWith('.md') || arg.endsWith('.markdown'))) {
      // Try to resolve the path (might be relative)
      const resolvedPath = path.isAbsolute(arg) ? arg : path.resolve(process.cwd(), arg);
      console.log('[MAIN] Resolved path:', resolvedPath);
      if (fs.existsSync(resolvedPath)) {
        // Store the file to open after window is ready
        console.log('[MAIN] Setting pendingFile to:', resolvedPath);
        app.pendingFile = resolvedPath;
        break;
      } else {
        console.log('[MAIN] File does not exist:', resolvedPath);
      }
    }
  }
  console.log('[MAIN] Final app.pendingFile:', app.pendingFile);
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

// IPC handlers for recent files
ipcMain.on('save-recent-files', (event, recentFiles) => {
  try {
    const userDataPath = app.getPath('userData');
    const recentFilesPath = path.join(userDataPath, 'recent-files.json');
    fs.writeFileSync(recentFilesPath, JSON.stringify(recentFiles, null, 2));
  } catch (error) {
    console.error('Error saving recent files:', error);
  }
});

ipcMain.on('clear-recent-files', (event) => {
  try {
    const userDataPath = app.getPath('userData');
    const recentFilesPath = path.join(userDataPath, 'recent-files.json');
    fs.writeFileSync(recentFilesPath, JSON.stringify([], null, 2));
    // Rebuild menu to reflect changes
    createMenu();
    event.reply('recent-files-cleared');
  } catch (error) {
    console.error('Error clearing recent files:', error);
  }
});

// Handle file opening on macOS
app.on('open-file', (event, filePath) => {
  event.preventDefault();
  if (mainWindow && rendererReady) {
    openFileFromPath(filePath);
  } else {
    // Store the file path to open after window and renderer are ready
    app.pendingFile = filePath;
  }
});

// Handle file opening from command line or file association
function openFileFromPath(filePath) {
  console.log('[MAIN] openFileFromPath called with:', filePath);
  console.log('[MAIN] rendererReady:', rendererReady, 'mainWindow exists:', !!mainWindow, 'webContents exists:', !!(mainWindow?.webContents));
  if (fs.existsSync(filePath)) {
    const stats = fs.statSync(filePath);
    if (stats.size > MAX_FILE_SIZE) {
        dialog.showErrorBox('File Too Large', `File exceeds the ${MAX_FILE_SIZE_MB}MB size limit.`);
        return;
    }
    currentFile = filePath;
    const content = fs.readFileSync(filePath, 'utf-8');
    console.log('[MAIN] File read successfully, content length:', content.length);
    console.log('[MAIN] About to send file-opened. mainWindow:', !!mainWindow, 'webContents:', !!(mainWindow?.webContents), 'rendererReady:', rendererReady);
    if (mainWindow && mainWindow.webContents && rendererReady) {
      // Send file immediately - renderer-ready means UI is initialized
      console.log('[MAIN] Sending file-opened to renderer');
      mainWindow.webContents.send('file-opened', { path: filePath, content });
    } else {
      // Store file to open after renderer is ready
      console.log('[MAIN] Storing as pending file');
      app.pendingFile = filePath;
    }
  } else {
    console.error('[MAIN] File does not exist:', filePath);
  }
}

// ========================================
// PDF OPERATIONS — delegates to main/PDFOperations.js
// ========================================

ipcMain.on('process-pdf-operation', async (event, data) => {
  try {
    mainWindow.webContents.send('pdf-operation-progress', {
      message: `Processing ${data.operation}...`,
      progress: 10
    });

    const result = await PDFOperations.executeOperation(data.operation, data);
    mainWindow.webContents.send('pdf-operation-complete', result);
  } catch (error) {
    mainWindow.webContents.send('pdf-operation-complete', {
      success: false,
      error: error.message
    });
  }
});

ipcMain.on('get-pdf-page-count', async (event, filePath) => {
  try {
    const count = await PDFOperations.getPageCount(filePath);
    event.reply('pdf-page-count', { count });
  } catch (error) {
    event.reply('pdf-page-count', { error: error.message });
  }
});

// IPC Handler for folder selection (for PDF operations)
ipcMain.on('select-pdf-folder', (event, inputId) => {
  const folder = dialog.showOpenDialogSync(mainWindow, {
    properties: ['openDirectory']
  });

  if (folder && folder[0]) {
    event.reply('pdf-folder-selected', { inputId, path: folder[0] });
  }
});

// ============================================
// ASCII Art Generator Window
// ============================================
let asciiGeneratorWindow = null;

function openAsciiGenerator() {
  if (asciiGeneratorWindow) {
    asciiGeneratorWindow.focus();
    return;
  }

  asciiGeneratorWindow = new BrowserWindow({
    width: 800,
    height: 700,
    parent: mainWindow,
    modal: false,
    title: 'ASCII Art Generator',
    icon: path.join(__dirname, '../assets/icon.png'),
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js')
    }
  });

  asciiGeneratorWindow.loadFile(path.join(__dirname, 'ascii-generator.html'));
  asciiGeneratorWindow.setMenuBarVisibility(false);

  asciiGeneratorWindow.on('closed', () => {
    asciiGeneratorWindow = null;
  });
}

ipcMain.on('open-ascii-generator', () => {
  openAsciiGenerator();
});

// ============================================
// Table Generator Window
// ============================================
let tableGeneratorWindow = null;

function openTableGenerator() {
  if (tableGeneratorWindow) {
    tableGeneratorWindow.focus();
    return;
  }

  tableGeneratorWindow = new BrowserWindow({
    width: 900,
    height: 700,
    parent: mainWindow,
    modal: false,
    title: 'Table Generator',
    icon: path.join(__dirname, '../assets/icon.png'),
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js')
    }
  });

  tableGeneratorWindow.loadFile(path.join(__dirname, 'table-generator.html'));
  tableGeneratorWindow.setMenuBarVisibility(false);

  tableGeneratorWindow.on('closed', () => {
    tableGeneratorWindow = null;
  });
}

ipcMain.on('open-table-generator', () => {
  openTableGenerator();
});

// IPC Handler for loading document templates
ipcMain.handle('load-template', async (event, filename) => {
  try {
    const templatePath = path.join(__dirname, 'templates', filename);
    return fs.readFileSync(templatePath, 'utf-8');
  } catch (err) {
    console.error('Failed to load template:', err);
    return null;
  }
});

// IPC Handler for saving pasted/dropped images
ipcMain.handle('save-pasted-image', async (event, { base64, ext }) => {
  try {
    let saveDir;

    if (currentFile) {
      // Save relative to current file
      saveDir = path.join(path.dirname(currentFile), 'assets');
    } else {
      // Use temp directory
      saveDir = path.join(app.getPath('temp'), 'markdown-converter-images');
    }

    if (!fs.existsSync(saveDir)) {
      fs.mkdirSync(saveDir, { recursive: true });
    }

    const filename = `image-${Date.now()}.${ext}`;
    const filePath = path.join(saveDir, filename);
    const buffer = Buffer.from(base64, 'base64');
    fs.writeFileSync(filePath, buffer);

    return { relativePath: `assets/${filename}`, absolutePath: filePath };
  } catch (error) {
    console.error('Failed to save pasted image:', error);
    return null;
  }
});

// IPC Handler to receive generated content from generator windows
ipcMain.on('insert-generated-content', (event, content) => {
  if (mainWindow && !mainWindow.isDestroyed()) {
    mainWindow.webContents.send('insert-content', content);
  }
});

// ============================================
// File Explorer IPC Handlers
// ============================================
ipcMain.handle('list-directory', async (event, dirPath) => {
  try {
    if (!dirPath) {
      const result = await dialog.showOpenDialog(mainWindow, {
        properties: ['openDirectory']
      });
      if (result.canceled || !result.filePaths[0]) return null;
      dirPath = result.filePaths[0];
    }

    // Validate path to prevent traversal attacks
    const validation = validatePath(dirPath);
    if (!validation.valid) {
      console.error('[SECURITY] Invalid directory path:', validation.error);
      return null;
    }

    if (!isPathAccessible(validation.resolved)) {
      return null;
    }

    const entries = fs.readdirSync(validation.resolved, { withFileTypes: true })
      .filter(e => !e.name.startsWith('.'))
      .sort((a, b) => {
        if (a.isDirectory() && !b.isDirectory()) return -1;
        if (!a.isDirectory() && b.isDirectory()) return 1;
        return a.name.localeCompare(b.name);
      })
      .map(e => ({
        name: e.name,
        isDirectory: e.isDirectory(),
        size: e.isDirectory() ? 0 : fs.statSync(path.join(validation.resolved, e.name)).size,
        modified: fs.statSync(path.join(validation.resolved, e.name)).mtimeMs,
        path: path.join(validation.resolved, e.name)
      }));
    return { path: validation.resolved, entries };
  } catch (err) {
    console.error('list-directory error:', err);
    return null;
  }
});

ipcMain.handle('select-custom-css', async (event) => {
  const result = dialog.showOpenDialogSync(mainWindow, {
    title: 'Select Custom Preview CSS',
    properties: ['openFile'],
    filters: [
      { name: 'CSS Stylesheets', extensions: ['css'] }
    ]
  });

  if (result && result[0]) {
    const filePath = result[0];
    const content = fs.readFileSync(filePath, 'utf-8');
    return { path: filePath, content };
  }
  return null;
});



ipcMain.handle('read-file', async (event, filePath) => {
  const validation = validatePath(filePath);
  if (!validation.valid || !isPathAccessible(validation.resolved)) {
    throw new Error(validation.error || 'Invalid file path');
  }

  return fs.readFileSync(validation.resolved, 'utf-8');
});

ipcMain.handle('write-file', async (event, payload) => {
  const validation = resolveWritablePath(payload?.path);
  if (!validation.valid) {
    throw new Error(validation.error || 'Invalid file path');
  }

  fs.mkdirSync(path.dirname(validation.resolved), { recursive: true });
  fs.writeFileSync(validation.resolved, payload?.content ?? '', 'utf-8');
  return { path: validation.resolved };
});

ipcMain.handle('delete-file', async (event, filePath) => {
  const validation = validatePath(filePath);
  if (!validation.valid || !isPathAccessible(validation.resolved)) {
    throw new Error(validation.error || 'Invalid file path');
  }

  fs.rmSync(validation.resolved, { recursive: true, force: false });
  return true;
});

ipcMain.handle('ensure-directory', async (event, dirPath) => {
  const validation = resolveWritablePath(dirPath);
  if (!validation.valid) {
    throw new Error(validation.error || 'Invalid directory path');
  }

  fs.mkdirSync(validation.resolved, { recursive: true });
  return validation.resolved;
});

ipcMain.handle('path-exists', async (event, filePath) => {
  const validation = resolveWritablePath(filePath);
  return validation.valid ? fs.existsSync(validation.resolved) : false;
});

ipcMain.handle('is-directory', async (event, filePath) => {
  const validation = validatePath(filePath);
  if (!validation.valid || !isPathAccessible(validation.resolved)) {
    return false;
  }

  return fs.statSync(validation.resolved).isDirectory();
});

ipcMain.handle('copy-path', async (event, payload) => {
  const sourceValidation = validatePath(payload?.source);
  const destinationValidation = resolveWritablePath(payload?.destination);

  if (!sourceValidation.valid || !isPathAccessible(sourceValidation.resolved)) {
    throw new Error(sourceValidation.error || 'Invalid source path');
  }
  if (!destinationValidation.valid) {
    throw new Error(destinationValidation.error || 'Invalid destination path');
  }

  fs.mkdirSync(path.dirname(destinationValidation.resolved), { recursive: true });
  fs.cpSync(sourceValidation.resolved, destinationValidation.resolved, { recursive: true });
  return { source: sourceValidation.resolved, destination: destinationValidation.resolved };
});

ipcMain.handle('move-path', async (event, payload) => {
  const sourceValidation = validatePath(payload?.source);
  const destinationValidation = resolveWritablePath(payload?.destination);

  if (!sourceValidation.valid || !isPathAccessible(sourceValidation.resolved)) {
    throw new Error(sourceValidation.error || 'Invalid source path');
  }
  if (!destinationValidation.valid) {
    throw new Error(destinationValidation.error || 'Invalid destination path');
  }

  fs.mkdirSync(path.dirname(destinationValidation.resolved), { recursive: true });

  try {
    fs.renameSync(sourceValidation.resolved, destinationValidation.resolved);
  } catch (error) {
    if (error.code !== 'EXDEV') {
      throw error;
    }

    fs.cpSync(sourceValidation.resolved, destinationValidation.resolved, { recursive: true });
    fs.rmSync(sourceValidation.resolved, { recursive: true, force: false });
  }

  return { source: sourceValidation.resolved, destination: destinationValidation.resolved };
});

// Open a file by path (from explorer panel)
ipcMain.on('open-file-path', (event, filePath) => {
  try {
    // Validate path to prevent traversal attacks
    const validation = validatePath(filePath);
    if (!validation.valid) {
      console.error('[SECURITY] Invalid file path:', validation.error);
      return;
    }

    if (!isPathAccessible(validation.resolved)) {
      return;
    }

    const stat = fs.statSync(validation.resolved);
    if (stat.size > MAX_FILE_SIZE) return;
    currentFile = validation.resolved;
    const content = fs.readFileSync(validation.resolved, 'utf-8');
    mainWindow.webContents.send('file-opened', { path: validation.resolved, content });
  } catch (err) {
    console.error('open-file-path error:', err);
  }
});

// ============================================
// Git IPC Handlers
// ============================================
ipcMain.handle('git-status', async () => {
  const dir = currentFile ? path.dirname(currentFile) : process.cwd();
  return GitOperations.getStatus(dir);
});

ipcMain.handle('git-stage', async (event, { files }) => {
  const dir = currentFile ? path.dirname(currentFile) : process.cwd();
  return GitOperations.stage(dir, files);
});

ipcMain.handle('git-commit', async (event, { message }) => {
  const dir = currentFile ? path.dirname(currentFile) : process.cwd();
  return GitOperations.commit(dir, message);
});

ipcMain.handle('git-log', async () => {
  const dir = currentFile ? path.dirname(currentFile) : process.cwd();
  return GitOperations.log(dir);
});

// ============================================
// Snippets IPC Handlers
// ============================================
const snippetsPath = path.join(app.getPath('userData'), 'snippets.json');

function loadSnippets() {
  try {
    if (fs.existsSync(snippetsPath)) {
      return JSON.parse(fs.readFileSync(snippetsPath, 'utf-8'));
    }
  } catch (err) { console.error('Failed to load snippets:', err); }
  return [];
}

function saveSnippetsFile(snippets) {
  fs.writeFileSync(snippetsPath, JSON.stringify(snippets, null, 2));
}

ipcMain.handle('get-snippets', async () => loadSnippets());

ipcMain.handle('save-snippet', async (event, snippet) => {
  const snippets = loadSnippets();
  const existing = snippets.findIndex(s => s.id === snippet.id);
  if (existing >= 0) snippets[existing] = snippet;
  else snippets.push(snippet);
  saveSnippetsFile(snippets);
  return snippets;
});

ipcMain.handle('delete-snippet', async (event, id) => {
  const snippets = loadSnippets().filter(s => s.id !== id);
  saveSnippetsFile(snippets);
  return snippets;
});

// ============================================
// Code Execution (REPL) IPC Handler
// ============================================
ipcMain.handle('execute-code', async (event, { code, language }) => {
  const timeout = 10000;

  return new Promise((resolve) => {
    let cmd, args;
    if (language === 'javascript' || language === 'js') {
      cmd = 'node';
      args = ['-e', code];
    } else if (language === 'python' || language === 'py') {
      cmd = process.platform === 'win32' ? 'python' : 'python3';
      args = ['-c', code];
    } else if (language === 'bash' || language === 'sh') {
      cmd = process.platform === 'win32' ? 'cmd' : 'bash';
      args = process.platform === 'win32' ? ['/c', code] : ['-c', code];
    } else {
      resolve({ error: `Unsupported language: ${language}` });
      return;
    }

    execFile(cmd, args, { timeout, maxBuffer: 1024 * 1024 }, (err, stdout, stderr) => {
      resolve({
        stdout: stdout || '',
        stderr: stderr || '',
        error: err?.killed ? 'Execution timed out (10s limit)' : (err?.message || null)
      });
    });
  });
});
