/**
 * desktopEnv.ts — Centralized Remote Desktop environment for the bridgesrd user.
 *
 * Problem: Every code path that launches something on the VNC desktop (projects,
 * agent browser, Chrome, xterm) had to reconstruct DISPLAY, XDG_RUNTIME_DIR,
 * PULSE_SERVER, SDL_AUDIODRIVER, DBUS vars, etc. Getting the quoting wrong in
 * `su -c` meant env vars were silently dropped, causing crashes (e.g. pygame
 * failing because ALSA couldn't find an audio device).
 *
 * Solution: One env file written at RD startup, one helper to launch commands.
 *
 * Usage:
 *   import { writeDesktopEnvFile, desktopExec, desktopExecDetached, DESKTOP_ENV_FILE } from '../utils/desktopEnv';
 *
 *   // During RD setup:
 *   writeDesktopEnvFile();
 *
 *   // To run a command as bridgesrd on the desktop:
 *   desktopExec('python3 main.py', { cwd: '/home/bridgesrd/projects/foo', timeout: 30000 });
 *
 *   // To launch a GUI app detached (xterm, Chrome, etc.):
 *   desktopExecDetached('xterm -e "python3 main.py"');
 */

import { execSync } from 'child_process';
import fs from 'fs';

export const RD_USER = 'bridgesrd';
export const DESKTOP_ENV_FILE = `/home/${RD_USER}/.bridges-rd-env`;

const DISPLAY = ':1';
const XDG_RUNTIME_DIR = '/tmp/bridges-rd-runtime';
const PULSE_SOCKET = `unix:${XDG_RUNTIME_DIR}/pulse/native`;

/**
 * The canonical set of environment variables needed to run GUI/audio apps
 * on the Remote Desktop. Add new vars here and every launch path gets them.
 */
export function getDesktopEnvVars(): Record<string, string> {
  return {
    DISPLAY,
    XDG_RUNTIME_DIR,
    PULSE_SERVER: PULSE_SOCKET,
    SDL_AUDIODRIVER: 'pulseaudio',
    // Prevent apt/dpkg noise when projects install system deps
    DEBIAN_FRONTEND: 'noninteractive',
  };
}

/**
 * Write the env file that all desktop launch paths source.
 * Called during Remote Desktop setup and on service restart.
 * The file is a plain shell script: `export KEY=VALUE` lines.
 */
export function writeDesktopEnvFile(): void {
  const vars = getDesktopEnvVars();
  const lines = Object.entries(vars).map(([k, v]) => `export ${k}=${shellQuote(v)}`);
  const content = [
    '# Auto-generated by BridgesLLM Portal — do not edit manually.',
    '# Sourced by all desktop launch paths (projects, Chrome, agent browser).',
    '# Regenerated on every Remote Desktop setup/restart.',
    '',
    ...lines,
    '',
  ].join('\n');

  fs.writeFileSync(DESKTOP_ENV_FILE, content, { mode: 0o640 });

  // Ensure bridgesrd can read it
  try {
    execSync(`chown ${RD_USER}:${RD_USER} ${shellQuote(DESKTOP_ENV_FILE)}`, { timeout: 3000 });
  } catch {
    // Non-fatal — file is world-readable anyway
  }
}

/**
 * Build a shell command string that sources the env file before running the
 * actual command. Falls back to inline exports if the env file doesn't exist
 * (e.g. older installs that haven't re-run RD setup).
 */
export function withDesktopEnv(cmd: string): string {
  const fallbackExports = Object.entries(getDesktopEnvVars())
    .map(([k, v]) => `export ${k}=${shellQuote(v)}`)
    .join('; ');

  // Source the env file if it exists, otherwise inline the exports.
  // Either way the command gets the right environment.
  return `if [ -f ${shellQuote(DESKTOP_ENV_FILE)} ]; then . ${shellQuote(DESKTOP_ENV_FILE)}; else ${fallbackExports}; fi; ${cmd}`;
}

/**
 * Execute a command as bridgesrd on the Remote Desktop (blocking).
 * The command inherits all desktop env vars.
 */
export function desktopExec(
  cmd: string,
  opts: { cwd?: string; timeout?: number } = {},
): string {
  const { cwd, timeout = 30000 } = opts;
  const cdPrefix = cwd ? `cd ${shellQuote(cwd)} && ` : '';
  const innerCmd = withDesktopEnv(`${cdPrefix}${cmd}`);
  const fullCmd = `su - ${RD_USER} -c ${shellQuote(innerCmd)}`;

  return execSync(fullCmd, {
    timeout,
    encoding: 'utf-8',
    shell: '/bin/bash',
  });
}

/**
 * Launch a GUI command as bridgesrd on the Remote Desktop (detached).
 * Returns immediately; the process continues in the background.
 * Use for xterm, Chrome, etc.
 */
export function desktopExecDetached(cmd: string): void {
  const innerCmd = withDesktopEnv(cmd);
  const fullCmd = `setsid su - ${RD_USER} -c ${shellQuote(innerCmd)} </dev/null >/dev/null 2>&1 &`;
  execSync(fullCmd, { timeout: 5000, shell: '/bin/bash' });
}

/** Shell-quote a string (single-quote wrapping with proper escaping). */
function shellQuote(s: string): string {
  return "'" + s.replace(/'/g, "'\\''") + "'";
}
