#!/usr/bin/env node
/**
 * Preuninstall Script
 *
 * Cleans up Ghostflow installation:
 * 1. Stops and unloads the launchd daemon
 * 2. Removes the app bundle from Application Support
 * 3. Optionally removes config and logs (with warning)
 */

import { execSync } from "node:child_process";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";

// ============================================================================
// Constants
// ============================================================================

const YELLOW = "\x1b[33m";
const GREEN = "\x1b[32m";
const DIM = "\x1b[2m";
const RESET = "\x1b[0m";

const LAUNCHD_LABEL = "com.ghostflow.daemon";
const LSREGISTER_PATH =
  "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister";

// ============================================================================
// Path Constants
// ============================================================================

const HOME_DIR = os.homedir();

/** Centralized path definitions for Ghostflow directories and files */
const PATHS = {
  launchAgentPlist: path.join(HOME_DIR, "Library", "LaunchAgents", `${LAUNCHD_LABEL}.plist`),
  appBundle: path.join(HOME_DIR, "Library", "Application Support", "ghostflow", "Ghostflow.app"),
  configDir: path.join(HOME_DIR, "Library", "Application Support", "ghostflow"),
  logsDir: path.join(HOME_DIR, "Library", "Logs", "ghostflow"),
};

// ============================================================================
// Cleanup Functions
// ============================================================================

/**
 * Safely execute a command, ignoring errors.
 * @param {string} command
 * @returns {boolean} true if command succeeded
 */
const safeExec = (command) => {
  try {
    execSync(command, { stdio: "ignore" });
    return true;
  } catch {
    return false;
  }
};

/**
 * Stop and unload the launchd daemon.
 * @returns {{ unloaded: boolean, reason?: string }}
 */
const unloadDaemon = () => {
  if (!fs.existsSync(PATHS.launchAgentPlist)) {
    return { unloaded: false, reason: "plist not found" };
  }

  // Stop and unload (ignore errors - may not be running/loaded)
  safeExec(`launchctl stop ${LAUNCHD_LABEL}`);
  safeExec(`launchctl unload "${PATHS.launchAgentPlist}"`);

  // Remove the plist file
  try {
    fs.unlinkSync(PATHS.launchAgentPlist);
    return { unloaded: true };
  } catch {
    return { unloaded: false, reason: "could not remove plist" };
  }
};

/**
 * Remove the app bundle from Application Support.
 * @returns {{ removed: boolean, reason?: string }}
 */
const removeAppBundle = () => {
  if (!fs.existsSync(PATHS.appBundle)) {
    return { removed: false, reason: "app bundle not found" };
  }

  try {
    fs.rmSync(PATHS.appBundle, { recursive: true, force: true });
    return { removed: true };
  } catch (err) {
    return { removed: false, reason: err.message };
  }
};

/**
 * Unregister from Launch Services.
 * @returns {boolean}
 */
const unregisterFromLaunchServices = () => {
  if (!fs.existsSync(LSREGISTER_PATH)) {
    return false;
  }

  return safeExec(`"${LSREGISTER_PATH}" -u "${PATHS.appBundle}"`);
};

/**
 * Print information about preserved directories.
 */
const printPreservedDirs = () => {
  const preserved = [
    { path: PATHS.configDir, label: "config", exists: fs.existsSync(PATHS.configDir) },
    { path: PATHS.logsDir, label: "logs", exists: fs.existsSync(PATHS.logsDir) },
  ].filter(({ exists }) => exists);

  if (preserved.length === 0) {
    return;
  }

  console.log();
  console.log(`${YELLOW}Note:${RESET} The following directories were preserved:`);
  preserved.forEach(({ path: dirPath, label }) => {
    console.log(`  ${DIM}${dirPath}${RESET} (${label})`);
  });
  console.log();
  console.log("  To remove all data, run:");
  console.log(`    rm -rf "${PATHS.configDir}" "${PATHS.logsDir}"`);
};

// ============================================================================
// Main
// ============================================================================

const main = () => {
  console.log(`${YELLOW}Uninstalling Ghostflow CLI...${RESET}`);
  console.log();

  // Only run on macOS
  if (os.platform() !== "darwin") {
    console.log(`${DIM}Skipping cleanup (not macOS)${RESET}`);
    return;
  }

  // Unregister from Launch Services first (while app still exists)
  unregisterFromLaunchServices();

  // Stop and unload daemon
  const daemonResult = unloadDaemon();
  if (daemonResult.unloaded) {
    console.log(`${GREEN}✓${RESET} Stopped and unloaded daemon`);
  } else {
    console.log(`${DIM}  Daemon not loaded (${daemonResult.reason})${RESET}`);
  }

  // Remove app bundle
  const appResult = removeAppBundle();
  if (appResult.removed) {
    console.log(`${GREEN}✓${RESET} Removed app bundle`);
  } else {
    console.log(`${DIM}  App bundle not found${RESET}`);
  }

  // Note about remaining files
  printPreservedDirs();

  console.log();
  console.log("Ghostflow uninstalled.");
};

main();
