// cli/commands/watchdog.js
// Manages the clauth watchdog Task Scheduler job on Windows.
// clauth watchdog install   — register job (UAC elevation)
// clauth watchdog uninstall — remove job (UAC elevation)
// clauth watchdog status    — check if job is registered and running
// clauth watchdog start     — start the job now without waiting for login

import { execSync, spawnSync } from "child_process";
import fs from "fs";
import path from "path";
import os from "os";
import { fileURLToPath } from "url";
import {
  getRegistryPath,
  getWatchdogStatuses,
  readWatchdogEvents,
  registerWatchdogManifest,
  restartWatchdogService,
} from "../watchdog-registry.js";

const __dirname  = path.dirname(fileURLToPath(import.meta.url));
const TASK_NAME  = "ClautWatchdog";
const APPDATA    = process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
const CLAUTH_DIR = path.join(APPDATA, "clauth");
const DEST_PS1   = path.join(CLAUTH_DIR, "watchdog.ps1");
const SOURCE_PS1 = path.join(__dirname, "..", "assets", "watchdog.ps1");
const PS_EXE     = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";

function ensureWatchdogScript() {
  fs.mkdirSync(CLAUTH_DIR, { recursive: true });
  fs.copyFileSync(SOURCE_PS1, DEST_PS1);
}

function isElevated() {
  try {
    const result = execSync(`${PS_EXE} -NoProfile -Command "([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)"`,
      { stdio: "pipe", encoding: "utf8" });
    return result.trim().toLowerCase() === "true";
  } catch { return false; }
}

// Build the PowerShell registration command as a single string
function buildRegisterCmd(ps1Path) {
  const escaped = ps1Path.replace(/'/g, "''");
  return [
    `$action  = New-ScheduledTaskAction -Execute 'powershell.exe'`,
    `  -Argument '-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File \\"${escaped}\\"';`,
    `$trigger  = New-ScheduledTaskTrigger -AtLogOn;`,
    `$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit 0 -RestartCount 3`,
    `  -RestartInterval (New-TimeSpan -Minutes 1) -MultipleInstances IgnoreNew;`,
    `Unregister-ScheduledTask -TaskName '${TASK_NAME}' -Confirm:$false -ErrorAction SilentlyContinue;`,
    `Register-ScheduledTask -TaskName '${TASK_NAME}' -Action $action -Trigger $trigger`,
    `  -Settings $settings -RunLevel Highest`,
    `  -Description 'clauth daemon watchdog — restarts on port 52437 if not responding.';`,
    `Write-Host 'Watchdog registered.'`,
  ].join(" ");
}

function buildUnregisterCmd() {
  return `Unregister-ScheduledTask -TaskName '${TASK_NAME}' -Confirm:$false -ErrorAction SilentlyContinue; Write-Host 'Watchdog removed.'`;
}

function runElevated(psCmd) {
  // Wrap in Start-Process -Verb RunAs to trigger UAC dialog
  const encoded = Buffer.from(psCmd, "utf16le").toString("base64");
  const result = spawnSync(PS_EXE, [
    "-NoProfile", "-Command",
    `Start-Process -FilePath '${PS_EXE}' -Verb RunAs -Wait -ArgumentList '-NoProfile -ExecutionPolicy Bypass -EncodedCommand ${encoded}'`,
  ], { stdio: "inherit", encoding: "utf8" });
  return result.status === 0;
}

function runDirect(psCmd) {
  const result = spawnSync(PS_EXE, [
    "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", psCmd,
  ], { stdio: "inherit", encoding: "utf8" });
  return result.status === 0;
}

function readScheduledTaskState() {
  try {
    const out = execSync(
      `${PS_EXE} -NoProfile -Command "Get-ScheduledTask -TaskName '${TASK_NAME}' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty State"`,
      { encoding: "utf8", stdio: ["pipe","pipe","pipe"], timeout: 5000 }
    ).trim();
    if (out) return out;
  } catch {}

  try {
    const out = execSync(`schtasks /Query /TN ${TASK_NAME} /FO LIST`, {
      encoding: "utf8",
      stdio: ["pipe","pipe","pipe"],
      timeout: 5000,
    });
    const status = out.match(/^Status:\\s*(.+)$/mi)?.[1]?.trim();
    return status || "Registered";
  } catch {
    return null;
  }
}

export async function runWatchdog(action, opts = {}) {
  if (action === "register") {
    const manifestPath = opts.manifest || opts.args?.[0];
    if (!manifestPath) {
      console.log("Usage: clauth watchdog register <manifest.json>");
      return;
    }
    const manifest = JSON.parse(fs.readFileSync(path.resolve(manifestPath), "utf8"));
    const result = registerWatchdogManifest(manifest);
    console.log(`Registered ${result.registered} watchdog service(s): ${result.services.join(", ")}`);
    console.log(`Registry: ${getRegistryPath()}`);
    return;
  }

  if (action === "list" || action === "services") {
    const status = await getWatchdogStatuses();
    console.log(JSON.stringify(status, null, 2));
    return;
  }

  if (action === "events") {
    const limit = opts.limit ? Number(opts.limit) : 100;
    console.log(JSON.stringify(readWatchdogEvents(limit), null, 2));
    return;
  }

  if (action === "restart") {
    const serviceId = opts.service || opts.args?.[0];
    if (!serviceId) {
      console.log("Usage: clauth watchdog restart <service-id>");
      return;
    }
    const result = restartWatchdogService(serviceId);
    console.log(JSON.stringify(result, null, 2));
    return;
  }

  if (os.platform() !== "win32") {
    console.log("Watchdog auto-start is Windows-only. On Linux/macOS, use systemd or launchd.");
    return;
  }

  if (action === "status" || !action) {
    const state = readScheduledTaskState();
    try {
      if (state) {
        console.log(`Watchdog task: ${TASK_NAME} — State: ${state}`);
        console.log(`Script:        ${DEST_PS1}`);
        console.log(`Log:           ${path.join(CLAUTH_DIR, "watchdog.log")}`);
        const status = await getWatchdogStatuses();
        console.log(`Services:      ${status.total} registered (${status.healthy} healthy, ${status.degraded} degraded, ${status.unreachable} unreachable)`);
        console.log(`Registry:      ${getRegistryPath()}`);
      } else {
        console.log(`Watchdog task '${TASK_NAME}' is NOT registered.`);
        console.log("Run: clauth watchdog install");
      }
    } catch {
      console.log(`Watchdog task '${TASK_NAME}' is NOT registered.`);
      console.log("Run: clauth watchdog install");
    }
    return;
  }

  if (action === "install") {
    ensureWatchdogScript();
    console.log(`\n  Installing clauth watchdog...`);
    console.log(`  Script: ${DEST_PS1}`);
    console.log(`  Task:   ${TASK_NAME} (runs at login)\n`);
    console.log("  Windows will ask for administrator approval — please click Yes.\n");

    const cmd = buildRegisterCmd(DEST_PS1);
    const ok  = isElevated() ? runDirect(cmd) : runElevated(cmd);

    if (ok) {
      console.log("\n  Watchdog installed. Starting now...");
      spawnSync(PS_EXE, [
        "-NoProfile", "-Command", `Start-ScheduledTask -TaskName '${TASK_NAME}'`,
      ], { stdio: "pipe" });
      console.log("  Done. Watchdog is running.\n");
    } else {
      console.log("\n  Installation cancelled or failed.");
      console.log(`  To install manually, run as Administrator:`);
      console.log(`    clauth watchdog install\n`);
    }
    return;
  }

  if (action === "uninstall") {
    console.log("\n  Removing clauth watchdog...");
    console.log("  Windows will ask for administrator approval — please click Yes.\n");
    const ok = isElevated() ? runDirect(buildUnregisterCmd()) : runElevated(buildUnregisterCmd());
    if (ok) console.log("\n  Watchdog removed.\n");
    else    console.log("\n  Removal cancelled or failed.\n");
    return;
  }

  if (action === "start") {
    console.log(`  Starting ${TASK_NAME}...`);
    const r = spawnSync(PS_EXE, [
      "-NoProfile", "-Command", `Start-ScheduledTask -TaskName '${TASK_NAME}'`,
    ], { stdio: "inherit", encoding: "utf8" });
    if (r.status === 0) console.log("  Watchdog started.");
    else console.log("  Could not start — is it registered? Run: clauth watchdog install");
    return;
  }

  console.log("Usage: clauth watchdog [install|uninstall|status|start|register|list|events|restart]");
}
