import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { Command } from "commander";
import chalk from "chalk";
import ora from "ora";
import { existsSync, readFileSync, unlinkSync } from "fs";
import { spawn } from "child_process";
import { join } from "path";
import {
  loadDaemonConfig,
  saveDaemonConfig,
  readDaemonStatus,
  getDaemonPaths,
  DEFAULT_DAEMON_CONFIG
} from "../../daemon/daemon-config.js";
function createDaemonCommand() {
  const cmd = new Command("daemon").description("Manage StackMemory unified daemon for background services").addHelpText(
    "after",
    `
Examples:
  stackmemory daemon start      Start the daemon
  stackmemory daemon stop       Stop the daemon
  stackmemory daemon status     Check daemon status
  stackmemory daemon logs       View daemon logs
  stackmemory daemon config     Show/edit configuration

The daemon provides:
  - Context auto-save (default: every 15 minutes)
  - Linear sync (optional, if configured)
  - File watch (optional, for change detection)
`
  );
  cmd.command("start").description("Start the unified daemon").option("--foreground", "Run in foreground (for debugging)").option("--save-interval <minutes>", "Context save interval in minutes").option("--linear-interval <minutes>", "Linear sync interval in minutes").option("--no-linear", "Disable Linear sync").option("--log-level <level>", "Log level (debug|info|warn|error)").action(async (options) => {
    const status = readDaemonStatus();
    if (status.running) {
      console.log(
        chalk.yellow("Daemon already running"),
        chalk.gray(`(pid: ${status.pid})`)
      );
      return;
    }
    const spinner = ora("Starting unified daemon...").start();
    try {
      const args = ["daemon-run"];
      if (options.saveInterval) {
        args.push("--save-interval", options.saveInterval);
      }
      if (options.linearInterval) {
        args.push("--linear-interval", options.linearInterval);
      }
      if (options.linear === false) {
        args.push("--no-linear");
      }
      if (options.logLevel) {
        args.push("--log-level", options.logLevel);
      }
      if (options.foreground) {
        spinner.stop();
        console.log(chalk.cyan("Running in foreground (Ctrl+C to stop)"));
        const { UnifiedDaemon } = await import("../../daemon/unified-daemon.js");
        const config = {};
        if (options.saveInterval) {
          config.context = {
            enabled: true,
            interval: parseInt(options.saveInterval, 10)
          };
        }
        if (options.linearInterval) {
          config.linear = {
            enabled: true,
            interval: parseInt(options.linearInterval, 10),
            retryAttempts: 3,
            retryDelay: 3e4
          };
        }
        if (options.linear === false) {
          config.linear = {
            enabled: false,
            interval: 60,
            retryAttempts: 3,
            retryDelay: 3e4
          };
        }
        const daemon = new UnifiedDaemon(config);
        await daemon.start();
        return;
      }
      const daemonScript = getDaemonScriptPath();
      if (!daemonScript) {
        spinner.fail(chalk.red("Daemon script not found"));
        return;
      }
      const daemonProcess = spawn("node", [daemonScript, ...args.slice(1)], {
        detached: true,
        stdio: "ignore",
        env: { ...process.env }
      });
      daemonProcess.unref();
      await new Promise((r) => setTimeout(r, 1e3));
      const newStatus = readDaemonStatus();
      if (newStatus.running) {
        spinner.succeed(chalk.green("Daemon started"));
        console.log(chalk.gray(`PID: ${newStatus.pid}`));
        const services = [];
        if (newStatus.services.context.enabled) services.push("context");
        if (newStatus.services.linear.enabled) services.push("linear");
        if (newStatus.services.fileWatch.enabled) services.push("file-watch");
        if (services.length > 0) {
          console.log(chalk.gray(`Services: ${services.join(", ")}`));
        }
      } else {
        spinner.fail(chalk.red("Failed to start daemon"));
        console.log(chalk.gray("Check logs: stackmemory daemon logs"));
      }
    } catch (error) {
      spinner.fail(chalk.red("Failed to start daemon"));
      console.log(chalk.gray(error.message));
    }
  });
  cmd.command("stop").description("Stop the unified daemon").action(() => {
    const status = readDaemonStatus();
    if (!status.running || !status.pid) {
      console.log(chalk.yellow("Daemon not running"));
      return;
    }
    try {
      process.kill(status.pid, "SIGTERM");
      console.log(chalk.green("Daemon stopped"));
    } catch (err) {
      console.log(chalk.red("Failed to stop daemon"));
      console.log(chalk.gray(err.message));
      const { pidFile } = getDaemonPaths();
      if (existsSync(pidFile)) {
        unlinkSync(pidFile);
        console.log(chalk.gray("Cleaned up stale PID file"));
      }
    }
  });
  cmd.command("restart").description("Restart the unified daemon").action(async () => {
    const status = readDaemonStatus();
    if (status.running && status.pid) {
      try {
        process.kill(status.pid, "SIGTERM");
        await new Promise((r) => setTimeout(r, 1e3));
      } catch {
      }
    }
    const config = loadDaemonConfig();
    const daemonScript = getDaemonScriptPath();
    if (!daemonScript) {
      console.log(chalk.red("Daemon script not found"));
      return;
    }
    const args = [];
    if (config.context.interval !== 15) {
      args.push("--save-interval", String(config.context.interval));
    }
    if (!config.linear.enabled) {
      args.push("--no-linear");
    } else if (config.linear.interval !== 60) {
      args.push("--linear-interval", String(config.linear.interval));
    }
    const daemonProcess = spawn("node", [daemonScript, ...args], {
      detached: true,
      stdio: "ignore"
    });
    daemonProcess.unref();
    await new Promise((r) => setTimeout(r, 1e3));
    const newStatus = readDaemonStatus();
    if (newStatus.running) {
      console.log(
        chalk.green("Daemon restarted"),
        chalk.gray(`(pid: ${newStatus.pid})`)
      );
    } else {
      console.log(chalk.red("Failed to restart daemon"));
    }
  });
  cmd.command("status").description("Check daemon status").action(() => {
    const status = readDaemonStatus();
    const config = loadDaemonConfig();
    console.log(chalk.bold("\nStackMemory Unified Daemon\n"));
    console.log(
      `Status: ${status.running ? chalk.green("Running") : chalk.yellow("Stopped")}`
    );
    if (status.running) {
      console.log(chalk.gray(`  PID: ${status.pid}`));
      if (status.uptime) {
        const uptime = Math.round(status.uptime / 1e3);
        const hours = Math.floor(uptime / 3600);
        const mins = Math.floor(uptime % 3600 / 60);
        const secs = uptime % 60;
        console.log(chalk.gray(`  Uptime: ${hours}h ${mins}m ${secs}s`));
      }
    }
    console.log("");
    console.log(chalk.bold("Services:"));
    const ctx = status.services.context;
    console.log(
      `  Context: ${ctx.enabled ? chalk.green("Enabled") : chalk.gray("Disabled")}`
    );
    if (ctx.enabled) {
      console.log(chalk.gray(`    Interval: ${config.context.interval} min`));
      if (ctx.saveCount) {
        console.log(chalk.gray(`    Saves: ${ctx.saveCount}`));
      }
      if (ctx.lastRun) {
        const ago = Math.round((Date.now() - ctx.lastRun) / 1e3 / 60);
        console.log(chalk.gray(`    Last save: ${ago} min ago`));
      }
    }
    const lin = status.services.linear;
    console.log(
      `  Linear: ${lin.enabled ? chalk.green("Enabled") : chalk.gray("Disabled")}`
    );
    if (lin.enabled) {
      console.log(chalk.gray(`    Interval: ${config.linear.interval} min`));
      if (config.linear.quietHours) {
        console.log(
          chalk.gray(
            `    Quiet hours: ${config.linear.quietHours.start}:00 - ${config.linear.quietHours.end}:00`
          )
        );
      }
      if (lin.syncCount) {
        console.log(chalk.gray(`    Syncs: ${lin.syncCount}`));
      }
    }
    const fw = status.services.fileWatch;
    console.log(
      `  FileWatch: ${fw.enabled ? chalk.green("Enabled") : chalk.gray("Disabled")}`
    );
    if (status.errors && status.errors.length > 0) {
      console.log("");
      console.log(chalk.bold("Recent Errors:"));
      status.errors.slice(-3).forEach((err) => {
        console.log(chalk.red(`  - ${err.slice(0, 80)}`));
      });
    }
    if (!status.running) {
      console.log("");
      console.log(chalk.bold("To start: stackmemory daemon start"));
    }
  });
  cmd.command("logs").description("View daemon logs").option("-n, --lines <number>", "Number of lines to show", "50").option("-f, --follow", "Follow log output").option("--level <level>", "Filter by log level").action((options) => {
    const { logFile } = getDaemonPaths();
    if (!existsSync(logFile)) {
      console.log(chalk.yellow("No log file found"));
      console.log(
        chalk.gray("Start the daemon first: stackmemory daemon start")
      );
      return;
    }
    if (options.follow) {
      const tail = spawn("tail", ["-f", logFile], { stdio: "inherit" });
      tail.on("error", () => {
        console.log(chalk.red("Could not follow logs"));
      });
      return;
    }
    const content = readFileSync(logFile, "utf8");
    const lines = content.trim().split("\n");
    const count = parseInt(options.lines, 10);
    let recent = lines.slice(-count);
    if (options.level) {
      const level = options.level.toUpperCase();
      recent = recent.filter((line) => {
        try {
          const entry = JSON.parse(line);
          return entry.level === level;
        } catch {
          return false;
        }
      });
    }
    console.log(chalk.bold(`
Daemon logs (${recent.length} lines):
`));
    for (const line of recent) {
      try {
        const entry = JSON.parse(line);
        const time = entry.timestamp.split("T")[1].split(".")[0];
        const levelColor = entry.level === "ERROR" ? chalk.red : entry.level === "WARN" ? chalk.yellow : entry.level === "DEBUG" ? chalk.gray : chalk.white;
        console.log(
          `${chalk.gray(time)} ${levelColor(`[${entry.level}]`)} ${chalk.cyan(`[${entry.service}]`)} ${entry.message}`
        );
      } catch {
        console.log(line);
      }
    }
  });
  cmd.command("config").description("Show or edit daemon configuration").option("--edit", "Open config in editor").option("--reset", "Reset to default configuration").option("--set <key=value>", "Set a config value").action((options) => {
    const { configFile } = getDaemonPaths();
    if (options.reset) {
      saveDaemonConfig(DEFAULT_DAEMON_CONFIG);
      console.log(chalk.green("Configuration reset to defaults"));
      return;
    }
    if (options.edit) {
      const editor = process.env["EDITOR"] || "vim";
      spawn(editor, [configFile], { stdio: "inherit" });
      return;
    }
    if (options.set) {
      const [key, value] = options.set.split("=");
      const config2 = loadDaemonConfig();
      const parts = key.split(".");
      let target = config2;
      for (let i = 0; i < parts.length - 1; i++) {
        if (target[parts[i]] && typeof target[parts[i]] === "object") {
          target = target[parts[i]];
        } else {
          console.log(chalk.red(`Invalid config key: ${key}`));
          return;
        }
      }
      const lastKey = parts[parts.length - 1];
      const parsed = value === "true" ? true : value === "false" ? false : isNaN(Number(value)) ? value : Number(value);
      target[lastKey] = parsed;
      saveDaemonConfig(config2);
      console.log(chalk.green(`Set ${key} = ${value}`));
      return;
    }
    const config = loadDaemonConfig();
    console.log(chalk.bold("\nDaemon Configuration\n"));
    console.log(chalk.gray(`File: ${configFile}`));
    console.log("");
    console.log(chalk.bold("Context Service:"));
    console.log(`  Enabled: ${config.context.enabled}`);
    console.log(`  Interval: ${config.context.interval} minutes`);
    console.log("");
    console.log(chalk.bold("Linear Service:"));
    console.log(`  Enabled: ${config.linear.enabled}`);
    console.log(`  Interval: ${config.linear.interval} minutes`);
    if (config.linear.quietHours) {
      console.log(
        `  Quiet hours: ${config.linear.quietHours.start}:00 - ${config.linear.quietHours.end}:00`
      );
    }
    console.log("");
    console.log(chalk.bold("File Watch:"));
    console.log(`  Enabled: ${config.fileWatch.enabled}`);
    console.log(`  Extensions: ${config.fileWatch.extensions.join(", ")}`);
    console.log("");
    console.log(chalk.bold("General:"));
    console.log(`  Heartbeat: ${config.heartbeatInterval} seconds`);
    console.log(`  Log level: ${config.logLevel}`);
  });
  cmd.action(() => {
    const status = readDaemonStatus();
    console.log(chalk.bold("\nStackMemory Daemon\n"));
    console.log(
      `Status: ${status.running ? chalk.green("Running") : chalk.yellow("Stopped")}`
    );
    if (!status.running) {
      console.log("");
      console.log(chalk.bold("Quick start:"));
      console.log("  stackmemory daemon start    Start background services");
    } else {
      console.log("");
      console.log(chalk.bold("Commands:"));
      console.log("  stackmemory daemon status   View detailed status");
      console.log("  stackmemory daemon logs     View daemon logs");
      console.log("  stackmemory daemon stop     Stop the daemon");
    }
  });
  return cmd;
}
function getDaemonScriptPath() {
  const candidates = [
    join(__dirname, "../../daemon/unified-daemon.js"),
    join(process.cwd(), "dist/daemon/unified-daemon.js"),
    join(
      process.cwd(),
      "node_modules/@stackmemoryai/stackmemory/dist/daemon/unified-daemon.js"
    )
  ];
  for (const candidate of candidates) {
    if (existsSync(candidate)) {
      return candidate;
    }
  }
  return candidates[0];
}
var daemon_default = createDaemonCommand();
export {
  createDaemonCommand,
  daemon_default as default
};
//# sourceMappingURL=daemon.js.map
