import { i as writeJsonFile } from "../json-store-WWsFzXub.js";
import { n as logger } from "../logger-Dyl4VcLO.js";
import path from "path";
import fs from "fs";
import { CronJob } from "cron";
//#region src/daemon/worker.ts
const DATA_DIR = process.env["DXCRM_DATA_DIR"] ?? process.cwd();
const MAX_CUSTOMERS_PER_CYCLE = 50;
async function syncWithBackoff(fn, maxRetries = 3) {
	for (let attempt = 0; attempt < maxRetries; attempt++) try {
		await fn();
		return;
	} catch (err) {
		const msg = err.message;
		if (msg.includes("429") || msg.includes("rateLimitExceeded")) {
			const delay = Math.pow(2, attempt) * 2e3;
			logger.warn("daemon", "rate limit, retrying", { delayMs: delay });
			await new Promise((r) => setTimeout(r, delay));
		} else throw err;
	}
}
async function syncAllCustomers() {
	const customersDir = path.join(DATA_DIR, "customers");
	if (!fs.existsSync(customersDir)) return;
	const slugsToSync = fs.readdirSync(customersDir).filter((s) => {
		try {
			return fs.statSync(path.join(customersDir, s)).isDirectory();
		} catch {
			return false;
		}
	}).slice(0, MAX_CUSTOMERS_PER_CYCLE);
	for (const slug of slugsToSync) {
		const sourcesPath = path.join(customersDir, slug, "sources.json");
		if (!fs.existsSync(sourcesPath)) continue;
		try {
			const sources = JSON.parse(fs.readFileSync(sourcesPath, "utf-8"));
			if (sources.gmail?.enabled && sources.gmail.query) {
				const tokenPath = path.join(DATA_DIR, ".agentic", "gmail-token.json");
				const credPath = path.join(DATA_DIR, ".agentic", "gmail-credentials.json");
				if (fs.existsSync(tokenPath) && fs.existsSync(credPath)) {
					const { getGmailAuth } = await import("../gmail-auth-OComS92L.js");
					const { syncGmail } = await import("../gmail-sync-SvECok5p.js");
					const auth = await getGmailAuth(credPath, tokenPath);
					await syncWithBackoff(async () => {
						const result = await syncGmail({
							slug,
							dataDir: DATA_DIR,
							auth,
							query: sources.gmail.query,
							since: /* @__PURE__ */ new Date(Date.now() - 1800 * 1e3)
						});
						if (result.synced > 0) logger.info("daemon", "synced emails", {
							slug,
							synced: result.synced
						});
						const { updateSlugSyncState } = await import("../sync-state-BaA8LbTI.js");
						updateSlugSyncState(DATA_DIR, slug, { lastGmailSync: (/* @__PURE__ */ new Date()).toISOString() });
					});
				}
			}
		} catch (err) {
			logger.error("daemon", "error syncing customer", {
				slug,
				error: err.message
			});
		}
	}
}
async function startWatcher() {
	const agenticSourcesPath = path.join(DATA_DIR, ".agentic", "sources.json");
	if (!fs.existsSync(agenticSourcesPath)) return;
	try {
		const sources = JSON.parse(fs.readFileSync(agenticSourcesPath, "utf-8"));
		if (sources.transcripts?.enabled && sources.transcripts.paths?.length) {
			const { watchTranscripts, processTranscriptFileAutoMatch } = await import("../transcript-watcher-BoClrJAz.js");
			watchTranscripts({
				paths: sources.transcripts.paths,
				extensions: sources.transcripts.extensions ?? [".txt", ".vtt"],
				dataDir: DATA_DIR,
				onFile: (filePath) => processTranscriptFileAutoMatch(filePath, DATA_DIR)
			});
			logger.info("daemon", "watching transcripts (LLM auto-match)");
		}
	} catch (err) {
		logger.error("daemon", "watcher error", { error: err.message });
	}
}
async function checkAgentWakeTriggers() {
	const agentsDir = path.join(DATA_DIR, ".agentic", "agents");
	if (!fs.existsSync(agentsDir)) return;
	const files = fs.readdirSync(agentsDir).filter((f) => f.endsWith(".agent.json"));
	for (const file of files) try {
		const config = JSON.parse(fs.readFileSync(path.join(agentsDir, file), "utf-8"));
		if (!config.wakeOn.includes("email")) continue;
		const { getLastGmailSync } = await import("../sync-state-BaA8LbTI.js");
		const lastSync = getLastGmailSync(DATA_DIR, config.slug);
		const lastWake = config.lastWake ? new Date(config.lastWake) : null;
		if (!lastSync) continue;
		if (lastWake && lastSync <= lastWake) continue;
		logger.info("daemon", "wake trigger", { slug: config.slug });
		const { buildContext } = await import("../context-builder-hmOPvgso.js");
		const context = await buildContext(DATA_DIR, config.slug).catch(() => null);
		if (!context) continue;
		if (config.channel === "telegram" && process.env["TELEGRAM_BOT_TOKEN"] && (config.telegramChatId ?? process.env["TELEGRAM_CHAT_ID"])) {
			const chatId = config.telegramChatId ?? process.env["TELEGRAM_CHAT_ID"];
			const token = process.env["TELEGRAM_BOT_TOKEN"];
			const message = `📬 New activity: *${config.slug}*\n\n${context.slice(0, 800)}`;
			try {
				const { default: https } = await import("https");
				const body = JSON.stringify({
					chat_id: chatId,
					text: message,
					parse_mode: "Markdown"
				});
				await new Promise((resolve, reject) => {
					const req = https.request(`https://api.telegram.org/bot${token}/sendMessage`, {
						method: "POST",
						headers: {
							"Content-Type": "application/json",
							"Content-Length": Buffer.byteLength(body)
						}
					}, (res) => {
						res.resume();
						resolve();
					});
					req.on("error", reject);
					req.write(body);
					req.end();
				});
				logger.info("daemon", "telegram sent", { slug: config.slug });
			} catch (err) {
				logger.error("daemon", "telegram failed", { error: err.message });
			}
		}
		config.lastWake = (/* @__PURE__ */ new Date()).toISOString();
		writeJsonFile(path.join(agentsDir, file), config);
	} catch (err) {
		logger.error("daemon", "agent check error", {
			file,
			error: err.message
		});
	}
}
/**
* Self-healing: each cycle, clean orphaned atomic-write temp files (a crash
* signature) and log any *failed* health checks (e.g. invalid customer data).
* Warn-level checks (log errors, stale backups) are intentionally not re-logged
* here to avoid a feedback loop — `dxcrm doctor` surfaces those on demand.
*/
async function runSelfHeal() {
	try {
		const { runDiagnostics, cleanupTempFiles } = await import("../doctor-CYDaNmFn.js");
		const removed = cleanupTempFiles(DATA_DIR);
		if (removed.length > 0) logger.warn("daemon", "self-heal: removed orphaned temp files", { count: removed.length });
		const report = await runDiagnostics(DATA_DIR);
		for (const check of report.checks) if (check.status === "fail") logger.error("daemon", `self-check failed: ${check.name}`, { detail: check.detail });
	} catch (err) {
		logger.error("daemon", "self-heal failed", { error: err.message });
	}
}
new CronJob(`*/${Math.max(1, parseInt(process.env["DXCRM_DAEMON_INTERVAL"] ?? "30", 10) || 30)} * * * *`, async () => {
	await syncAllCustomers();
	await checkAgentWakeTriggers().catch((err) => {
		logger.error("daemon", "wake trigger check failed", { error: err.message });
	});
	await runSelfHeal();
}, null, true, void 0, null, false, void 0, false, true);
new CronJob("*/60 * * * *", async () => {
	try {
		const { runScheduledBackupIfDue } = await import("../backup-LFnC09oV.js");
		await runScheduledBackupIfDue(DATA_DIR);
	} catch (err) {
		logger.error("daemon", "backup check error", { error: err.message });
	}
}, null, true, void 0, null, false, void 0, false, true);
new CronJob("0 6 * * *", async () => {
	try {
		const { renewExpiringSubscriptions } = await import("../push-manager-BXM-IHfP.js");
		const { buildGmailRenewFn } = await import("../gmail-webhook-handler-CvSDW_Js.js");
		const tokenPath = path.join(DATA_DIR, ".agentic", "gmail-token.json");
		const credPath = path.join(DATA_DIR, ".agentic", "gmail-credentials.json");
		const { readSubscriptions } = await import("../push-manager-BXM-IHfP.js");
		if ((await readSubscriptions(DATA_DIR)).filter((s) => s.provider === "gmail" && s.status === "active").length === 0) return;
		if (!fs.existsSync(tokenPath) || !fs.existsSync(credPath)) return;
		const { getGmailAuth } = await import("../gmail-auth-OComS92L.js");
		const result = await renewExpiringSubscriptions(DATA_DIR, buildGmailRenewFn((await getGmailAuth(credPath, tokenPath)).credentials?.access_token ?? "", ""), 24);
		if (result.renewed.length > 0) logger.info("push", "renewed subscriptions", { count: result.renewed.length });
		if (result.errors.length > 0) logger.warn("push", "renewal errors", { errors: result.errors });
	} catch (err) {
		logger.error("push", "renewal failed", { error: err.message });
	}
}, null, true, void 0, null, false, void 0, false, true);
new CronJob("0 7 * * *", async () => {
	try {
		const { runDailyProactiveChecks } = await import("../proactive-worker-1zkm6aJD.js");
		const result = await runDailyProactiveChecks(DATA_DIR);
		logger.info("proactive", "daily check", {
			customersChecked: result.customersChecked,
			tasksEnqueued: result.tasksEnqueued
		});
		if (result.errors.length > 0) logger.warn("proactive", "errors during daily check", { errors: result.errors });
		const { drainProactiveQueue } = await import("../notification-dispatcher-inpKyuBz.js");
		const drain = await drainProactiveQueue(DATA_DIR);
		logger.info("proactive", "dispatched tasks", {
			sent: drain.sent,
			failed: drain.failed
		});
		const { syncGoalProgressFromPipeline } = await import("../goal-engine-CfDAJTFt.js");
		const goalSync = await syncGoalProgressFromPipeline(DATA_DIR);
		if (goalSync.updated.length > 0) logger.info("goals", "progress synced", { updated: goalSync.updated });
	} catch (err) {
		logger.error("proactive", "daily check failed", { error: err.message });
	}
}, null, true, void 0, null, false, void 0, false, true);
new CronJob("0 8 * * *", async () => {
	try {
		const { checkSlaBreaches } = await import("../sla-engine-CP2KiKDS.js");
		const breaches = await checkSlaBreaches(DATA_DIR, (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
		if (breaches.length > 0) {
			logger.warn("tickets", "SLA breaches found", { count: breaches.length });
			for (const { slug, ticket } of breaches) logger.warn("tickets", "SLA breach", {
				slug,
				ticketId: ticket.id,
				title: ticket.title,
				due: ticket.slaDue
			});
		}
	} catch (err) {
		logger.error("tickets", "SLA check failed", { error: err.message });
	}
}, null, true, void 0, null, false, void 0, false, true);
new CronJob("0 */6 * * *", async () => {
	try {
		const { runSequenceCycle } = await import("../sequence-engine-C6nnewHX.js");
		const result = await runSequenceCycle(DATA_DIR, (/* @__PURE__ */ new Date()).toISOString().slice(0, 10));
		logger.info("sequences", "cycle complete", {
			sent: result.sent,
			completed: result.completed,
			errors: result.errors.length
		});
	} catch (err) {
		logger.error("sequences", "cycle failed", { error: err.message });
	}
}, null, true, void 0, null, false, void 0, false, true);
await startWatcher();
if (process.send) process.send("ready");
logger.info("daemon", "daemon started");
//#endregion
export {};

//# sourceMappingURL=worker.js.map