import { exec, execScript } from "../ssh";
import type { AgentRunner, AgentRunnerCtx } from "./types";

// OpenClaw: tiền nhiệm của Hermes Agent (cùng base codebase). Cài qua npm/pip
// hoặc script, vận hành tương tự Hermes (CLI + gateway). Dùng systemd cho daemon.
// Nếu repo cụ thể của user khác, sửa biến INSTALL_CMD bên dưới.

const INSTALL_CMD =
  "command -v openclaw >/dev/null 2>&1 || " +
  "(curl -fsSL https://raw.githubusercontent.com/NousResearch/openclaw/main/scripts/install.sh | bash 2>&1 | tail -20 || " +
  " npm i -g openclaw@latest --no-audit --no-fund 2>&1 | tail -20)";

function unitName(ctx: AgentRunnerCtx) {
  return `agent-${ctx.name}.service`;
}
function workdir(ctx: AgentRunnerCtx) {
  return `${ctx.installPath}/${ctx.name}`;
}

const SYSTEMD_TEMPLATE = (name: string, wd: string) => `
[Unit]
Description=Agent-Manager managed OpenClaw (${name})
After=network.target

[Service]
Type=simple
WorkingDirectory=${wd}
Environment=HOME=/root
ExecStart=/bin/bash -lc 'openclaw gateway run'
Restart=on-failure
RestartSec=5
StandardOutput=append:/var/log/agent-${name}.log
StandardError=append:/var/log/agent-${name}.log

[Install]
WantedBy=multi-user.target
`.trim();

export const openclawRunner: AgentRunner = {
  kind: "openclaw",

  async install(ctx) {
    const wd = workdir(ctx);
    const unit = unitName(ctx);
    const r = await execScript(ctx.hostId, [
      { label: "base deps", cmd: "apt-get update -q 2>&1 | tail -3 && DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl ca-certificates python3 python3-venv git build-essential 2>&1 | tail -3" },
      { label: "install openclaw", cmd: INSTALL_CMD },
      { label: "verify binary", cmd: "bash -lc 'openclaw --version 2>&1 | head -1' || (echo 'openclaw not on PATH'; ls /root/.local/bin/openclaw 2>/dev/null)" },
      { label: "scaffold workdir", cmd: `mkdir -p ${wd}` },
      { label: "write systemd unit", cmd: `cat > /etc/systemd/system/${unit} <<'EOF'\n${SYSTEMD_TEMPLATE(ctx.name, wd)}\nEOF\nsystemctl daemon-reload` },
    ], { timeoutMsPerStep: 300_000 });
    const v = await exec(ctx.hostId, "openclaw --version 2>&1 | head -1");
    return { ok: r.ok, log: r.log, version: v.stdout.trim() || undefined };
  },

  async update(ctx) {
    const r = await execScript(ctx.hostId, [
      { label: "openclaw update", cmd: "openclaw update 2>&1 | tail -20 || npm i -g openclaw@latest --no-audit --no-fund 2>&1 | tail -20" },
      { label: "version", cmd: "openclaw --version 2>&1 | head -1" },
      { label: "restart unit", cmd: `systemctl is-enabled ${unitName(ctx)} >/dev/null 2>&1 && systemctl restart ${unitName(ctx)} || true` },
    ], { timeoutMsPerStep: 300_000 });
    const v = await exec(ctx.hostId, "openclaw --version 2>&1 | head -1");
    return { ok: r.ok, log: r.log, version: v.stdout.trim() || undefined };
  },

  async status(ctx) {
    const v = await exec(ctx.hostId, "openclaw --version 2>&1 | head -1");
    const s = await exec(ctx.hostId, `systemctl is-active ${unitName(ctx)} 2>/dev/null; systemctl show ${unitName(ctx)} -p MainPID --value 2>/dev/null`);
    const lines = s.stdout.trim().split("\n");
    const active = lines[0]?.trim() === "active";
    const pid = parseInt(lines[1] || "0", 10) || undefined;
    return {
      ok: true,
      log: `version: ${v.stdout.trim()}\nunit: ${lines[0]}\npid: ${pid ?? "-"}`,
      version: v.stdout.trim() || undefined,
      running: active,
      pid: active ? pid : undefined,
    };
  },

  async start(ctx) {
    const r = await execScript(ctx.hostId, [
      { label: "enable+start", cmd: `systemctl enable --now ${unitName(ctx)}` },
      { label: "status", cmd: `systemctl is-active ${unitName(ctx)}` },
    ]);
    return { ok: r.ok, log: r.log };
  },

  async stop(ctx) {
    const r = await execScript(ctx.hostId, [{ label: "stop", cmd: `systemctl stop ${unitName(ctx)}` }]);
    return { ok: r.ok, log: r.log };
  },

  async logs(ctx, lines = 200) {
    const r = await exec(ctx.hostId, `tail -n ${lines} /var/log/agent-${ctx.name}.log 2>/dev/null || journalctl -u ${unitName(ctx)} -n ${lines} --no-pager`, { timeoutMs: 15_000 });
    return { ok: true, log: r.stdout || r.stderr };
  },

  async uninstall(ctx) {
    const wd = workdir(ctx);
    const r = await execScript(ctx.hostId, [
      { label: "stop+disable", cmd: `systemctl disable --now ${unitName(ctx)} 2>/dev/null || true` },
      { label: "rm unit", cmd: `rm -f /etc/systemd/system/${unitName(ctx)} && systemctl daemon-reload` },
      { label: "rm workdir", cmd: `rm -rf ${wd}` },
      { label: "rm log", cmd: `rm -f /var/log/agent-${ctx.name}.log` },
    ], { stopOnFail: false });
    return { ok: r.ok, log: r.log };
  },
};
