import { createLogger } from "../utils/logger/index.js";
import { init_logger } from "../utils/logger.js";
import { resolveGatewayWindowsTaskName } from "./constants.js";
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
import path from "node:path";
import os from "node:os";
import { spawn, spawnSync } from "node:child_process";
//#region src/daemon/schtasks.ts
/**
* Scheduled Task Service - Windows service management via schtasks
*
* Aligned with OpenClaw Windows implementation:
* - Task with ONLOGON trigger for persistence
* - RepetitionInterval for keep-alive behavior
* - Proper start/stop/restart lifecycle
*/
init_logger();
const log = createLogger("SchtasksService");
function resolveProfileFromEnv(env) {
	return env?.XOPC_PROFILE?.trim() || void 0;
}
function resolveTaskName(env) {
	return resolveGatewayWindowsTaskName(resolveProfileFromEnv(env));
}
async function schtasks(args) {
	return new Promise((resolve, reject) => {
		const child = spawn("schtasks", args, { stdio: [
			"ignore",
			"pipe",
			"pipe"
		] });
		let stdout = "";
		let stderr = "";
		child.stdout?.on("data", (data) => {
			stdout += data.toString();
		});
		child.stderr?.on("data", (data) => {
			stderr += data.toString();
		});
		child.on("close", (code) => {
			resolve({
				stdout,
				stderr,
				exitCode: code
			});
		});
		child.on("error", (err) => {
			reject(/* @__PURE__ */ new Error(`schtasks spawn failed: ${err.message}`));
		});
	});
}
async function schtasksExec(args) {
	const result = await schtasks(args);
	if (result.exitCode !== 0) {
		const detail = result.stderr.trim() || result.stdout.trim();
		throw new Error(`schtasks failed (exit ${result.exitCode}): ${detail}`);
	}
	return result.stdout;
}
function resolveTaskDaemonDir() {
	return path.join(os.homedir(), ".xopc", "daemon");
}
function resolveTaskEnvSidecarPath(taskName) {
	return path.join(resolveTaskDaemonDir(), `${taskName}.env.json`);
}
function resolveTaskCommandSidecarPath(taskName) {
	return path.join(resolveTaskDaemonDir(), `${taskName}.command.json`);
}
function resolveTaskWrapperPath(taskName) {
	return path.join(resolveTaskDaemonDir(), `${taskName}.cmd`);
}
function resolveTaskXmlPath(taskName) {
	return path.join(resolveTaskDaemonDir(), `${taskName}.xml`);
}
function escapeCmdSetValue(value) {
	return value.replace(/\^/g, "^^").replace(/%/g, "%%").replace(/"/g, "^\"").replace(/&/g, "^&").replace(/</g, "^<").replace(/>/g, "^>").replace(/\|/g, "^|");
}
function quoteCmdArg(value) {
	return `"${value.replace(/"/g, "\\\"")}"`;
}
function escapeXmlValue(value) {
	return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
}
function buildTaskWrapperContent(params) {
	const lines = ["@echo off"];
	for (const [key, value] of Object.entries(params.environment ?? {})) lines.push(`set "${key}=${escapeCmdSetValue(value)}"`);
	if (params.workingDirectory) lines.push(`cd /d ${quoteCmdArg(params.workingDirectory)}`);
	lines.push(params.programArguments.map(quoteCmdArg).join(" "));
	return `${lines.join("\r\n")}\r\n`;
}
function buildTaskXml(params) {
	const escapedDescription = escapeXmlValue(params.description);
	const escapedWrapperPath = escapeXmlValue(params.wrapperPath);
	const escapedWorkingDirectory = params.workingDirectory ? escapeXmlValue(params.workingDirectory) : "";
	return `<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Description>${escapedDescription}</Description>
  </RegistrationInfo>
  <Triggers>
    <LogonTrigger>
      <Enabled>true</Enabled>
    </LogonTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <LogonType>InteractiveToken</LogonType>
      <RunLevel>LeastPrivilege</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>false</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
    <Priority>7</Priority>
    <RestartOnFailure>
      <Interval>PT1M</Interval>
      <Count>999</Count>
    </RestartOnFailure>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>${escapedWrapperPath}</Command>${escapedWorkingDirectory ? `\n      <WorkingDirectory>${escapedWorkingDirectory}</WorkingDirectory>` : ""}
    </Exec>
  </Actions>
</Task>
`;
}
function writeTaskEnvSidecar(taskName, environment) {
	const sidecarPath = resolveTaskEnvSidecarPath(taskName);
	try {
		mkdirSync(path.dirname(sidecarPath), { recursive: true });
		writeFileSync(sidecarPath, JSON.stringify(environment, null, 2), "utf8");
	} catch (err) {
		log.warn({
			err,
			sidecarPath
		}, "Failed to write task environment sidecar");
	}
}
function readTaskEnvSidecar(taskName) {
	const sidecarPath = resolveTaskEnvSidecarPath(taskName);
	try {
		const raw = readFileSync(sidecarPath, "utf8");
		const parsed = JSON.parse(raw);
		if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
	} catch {}
}
function writeTaskCommandSidecar(taskName, args) {
	const sidecarPath = resolveTaskCommandSidecarPath(taskName);
	try {
		writeFileSync(sidecarPath, JSON.stringify({
			programArguments: args.programArguments,
			workingDirectory: args.workingDirectory
		}, null, 2), "utf8");
	} catch (err) {
		log.warn({
			err,
			sidecarPath
		}, "Failed to write task command sidecar");
	}
}
function readTaskCommandSidecar(taskName) {
	const sidecarPath = resolveTaskCommandSidecarPath(taskName);
	try {
		const raw = readFileSync(sidecarPath, "utf8");
		const parsed = JSON.parse(raw);
		if (parsed && typeof parsed === "object" && Array.isArray(parsed.programArguments) && parsed.programArguments.every((arg) => typeof arg === "string")) return {
			programArguments: parsed.programArguments,
			workingDirectory: typeof parsed.workingDirectory === "string" ? parsed.workingDirectory : void 0
		};
	} catch {}
	return null;
}
function writeTaskSupportFiles(taskName, args) {
	const wrapperPath = resolveTaskWrapperPath(taskName);
	const xmlPath = resolveTaskXmlPath(taskName);
	mkdirSync(resolveTaskDaemonDir(), { recursive: true });
	writeFileSync(wrapperPath, buildTaskWrapperContent({
		programArguments: args.programArguments,
		workingDirectory: args.workingDirectory,
		environment: args.environment
	}), "utf8");
	writeFileSync(xmlPath, buildTaskXml({
		description: args.description || "xopc Gateway Service",
		wrapperPath,
		workingDirectory: args.workingDirectory
	}), "utf16le");
	writeTaskEnvSidecar(taskName, args.environment ?? {});
	writeTaskCommandSidecar(taskName, args);
	return {
		wrapperPath,
		xmlPath
	};
}
function removeTaskSupportFiles(taskName) {
	for (const filePath of [
		resolveTaskEnvSidecarPath(taskName),
		resolveTaskCommandSidecarPath(taskName),
		resolveTaskWrapperPath(taskName),
		resolveTaskXmlPath(taskName)
	]) try {
		rmSync(filePath, { force: true });
	} catch {}
}
const schtasksTestInternals = {
	buildTaskWrapperContent,
	buildTaskXml,
	escapeCmdSetValue,
	quoteCmdArg,
	resolveTaskCommandSidecarPath,
	resolveTaskWrapperPath,
	resolveTaskXmlPath
};
function isSchtasksAvailable() {
	if (process.platform !== "win32") return false;
	try {
		return spawnSync("schtasks", ["/query", "/?"], {
			stdio: [
				"ignore",
				"ignore",
				"ignore"
			],
			timeout: 3e3
		}).status === 0;
	} catch {
		return false;
	}
}
const schtasksService = {
	label: resolveGatewayWindowsTaskName(),
	loadedText: "Scheduled Task (installed)",
	notLoadedText: "Scheduled Task (not installed)",
	async install(args) {
		const taskName = resolveTaskName(args.env);
		try {
			await schtasks([
				"/delete",
				"/tn",
				taskName,
				"/f"
			]);
		} catch {}
		const { wrapperPath, xmlPath } = writeTaskSupportFiles(taskName, args);
		await schtasksExec([
			"/create",
			"/tn",
			taskName,
			"/xml",
			xmlPath,
			"/f"
		]);
		args.stdout?.write(`Created scheduled task: ${taskName}\n`);
		args.stdout?.write(`  Wrapper: ${wrapperPath}\n`);
		args.stdout?.write(`  Command: ${args.programArguments.join(" ")}\n`);
		log.info({
			taskName,
			wrapperPath
		}, "Scheduled task installed");
	},
	async uninstall(args) {
		const taskName = resolveTaskName(args.env);
		try {
			await schtasks([
				"/end",
				"/tn",
				taskName
			]);
		} catch {}
		try {
			await schtasksExec([
				"/delete",
				"/tn",
				taskName,
				"/f"
			]);
			args.stdout?.write(`Deleted scheduled task: ${taskName}\n`);
		} catch (err) {
			log.debug({ err }, "Uninstall task not found");
		}
		removeTaskSupportFiles(taskName);
		log.info({ taskName }, "Scheduled task uninstalled");
	},
	async stop(args) {
		const taskName = resolveTaskName(args.env);
		try {
			await schtasksExec([
				"/end",
				"/tn",
				taskName
			]);
		} catch {
			log.debug("Task not running");
		}
		if (args.disable) try {
			await schtasksExec([
				"/change",
				"/tn",
				taskName,
				"/disable"
			]);
		} catch {}
		log.info("Scheduled task stopped");
	},
	async restart(args) {
		const taskName = resolveTaskName(args.env);
		try {
			await schtasks([
				"/end",
				"/tn",
				taskName
			]);
		} catch {}
		await new Promise((resolve) => setTimeout(resolve, 500));
		await schtasksExec([
			"/run",
			"/tn",
			taskName
		]);
		log.info("Scheduled task restarted");
		return { outcome: "restarted" };
	},
	async isLoaded(args) {
		return (await schtasks([
			"/query",
			"/tn",
			resolveTaskName(args.env)
		])).exitCode === 0;
	},
	async readRuntime(env) {
		const taskName = resolveTaskName(env);
		try {
			const result = await schtasks([
				"/query",
				"/tn",
				taskName,
				"/fo",
				"list",
				"/v"
			]);
			if (result.exitCode !== 0) return { status: "unknown" };
			const output = result.stdout;
			let status = "unknown";
			const statusMatch = output.match(/Status:\s*(\w+)/i);
			if (statusMatch) {
				const statusStr = statusMatch[1].toLowerCase();
				if (statusStr === "running") status = "running";
				else if (statusStr === "ready" || statusStr === "disabled") status = "stopped";
			}
			let lastExitStatus;
			const resultMatch = output.match(/Last Result:\s*(\d+)/i);
			if (resultMatch) lastExitStatus = parseInt(resultMatch[1], 10);
			return {
				status,
				lastExitStatus
			};
		} catch {
			return { status: "unknown" };
		}
	},
	async readCommand(env) {
		const taskName = resolveTaskName(env);
		try {
			if ((await schtasks([
				"/query",
				"/tn",
				taskName,
				"/fo",
				"list",
				"/v"
			])).exitCode !== 0) return null;
			const commandSidecar = readTaskCommandSidecar(taskName);
			if (!commandSidecar) return null;
			return {
				programArguments: commandSidecar.programArguments,
				workingDirectory: commandSidecar.workingDirectory,
				environment: readTaskEnvSidecar(taskName)
			};
		} catch {
			return null;
		}
	}
};
//#endregion
export { isSchtasksAvailable, schtasksService, schtasksTestInternals };

//# sourceMappingURL=schtasks.js.map