import { i as writeJsonFile } from "./json-store-WWsFzXub.js";
import { u as runScheduledBackupIfDue } from "./backup-CTlIxUdO.js";
import { t as readPipeline } from "./pipeline-writer-CIllfnZl.js";
import { n as readHealth, t as computeCustomerHealth } from "./relationship-health-ZZNXR1RZ.js";
import { n as enqueueTask, t as buildDailyBriefing } from "./proactive-agent-B7u3Bj_l.js";
import path from "path";
import fs from "fs";
import https from "https";
//#region src/sync/external-signals.ts
function signalsDir(dataDir, slug) {
	return path.join(dataDir, "customers", slug, "signals");
}
function signalsFilePath(dataDir, slug, date) {
	return path.join(signalsDir(dataDir, slug), `${date}.json`);
}
function writeSignals(dataDir, slug, date, signals) {
	writeJsonFile(signalsFilePath(dataDir, slug, date), signals);
}
async function fetchJson(url, headers = {}) {
	return new Promise((resolve, reject) => {
		const u = new URL(url);
		const options = {
			hostname: u.hostname,
			path: u.pathname + u.search,
			method: "GET",
			headers: {
				"User-Agent": "datasynx-opencrm/2.0",
				...headers
			}
		};
		const req = https.request(options, (res) => {
			let data = "";
			res.on("data", (chunk) => {
				data += chunk.toString();
			});
			res.on("end", () => {
				try {
					resolve(JSON.parse(data));
				} catch (e) {
					reject(e);
				}
			});
		});
		req.on("error", reject);
		req.setTimeout(5e3, () => {
			req.destroy();
			reject(/* @__PURE__ */ new Error("timeout"));
		});
		req.end();
	});
}
async function checkCompanyNews(domain, companyName) {
	const signals = [];
	try {
		const query = encodeURIComponent(companyName.split(" ")[0] ?? domain.split(".")[0] ?? "");
		const result = await fetchJson(`https://hn.algolia.com/api/v1/search?query=${query}&tags=story&numericFilters=created_at_i>${Math.floor(Date.now() / 1e3) - 30 * 86400}&hitsPerPage=5`);
		for (const hit of result.hits ?? []) {
			const title = hit.title ?? hit.story_title ?? "";
			if (!title.toLowerCase().includes(query.toLowerCase())) continue;
			const titleLc = title.toLowerCase();
			const type = titleLc.includes("fund") ? "funding_round" : titleLc.includes("acqui") ? "acquisition" : titleLc.includes("lay") || titleLc.includes("reduc") ? "layoffs" : "news_mention";
			const impact = type === "funding_round" || type === "acquisition" ? "positive" : type === "layoffs" ? "negative" : "neutral";
			signals.push({
				id: `hn_${hit.objectID}`,
				slug: "",
				source: "hacker_news",
				type,
				summary: title,
				url: hit.url ?? `https://news.ycombinator.com/item?id=${hit.objectID}`,
				detectedAt: (/* @__PURE__ */ new Date()).toISOString(),
				impact
			});
		}
	} catch {}
	return signals;
}
async function checkFundingEvents(domain) {
	const apiKey = process.env["CRUNCHBASE_API_KEY"];
	if (!apiKey) return [];
	const signals = [];
	try {
		const props = (await fetchJson(`https://api.crunchbase.com/api/v4/entities/organizations/${domain.split(".")[0] ?? domain}?field_ids=short_description,funding_total,last_funding_type&user_key=${apiKey}`)).data?.properties;
		if (props?.last_funding_type && props?.funding_total?.value_usd) {
			const millions = (props.funding_total.value_usd / 1e6).toFixed(1);
			signals.push({
				id: `cb_${domain}_${Date.now()}`,
				slug: "",
				source: "crunchbase",
				type: "funding_round",
				summary: `${domain} raised funding (${props.last_funding_type}, $${millions}M total)`,
				detectedAt: (/* @__PURE__ */ new Date()).toISOString(),
				impact: "positive"
			});
		}
	} catch {}
	return signals;
}
async function fetchSignalsForCustomer(dataDir, slug, domain, companyName, today) {
	const [newsSignals, fundingSignals] = await Promise.all([checkCompanyNews(domain, companyName), checkFundingEvents(domain)]);
	const signals = [...newsSignals.map((s) => ({
		...s,
		slug
	})), ...fundingSignals.map((s) => ({
		...s,
		slug
	}))];
	if (signals.length > 0) writeSignals(dataDir, slug, today, signals);
	return signals;
}
//#endregion
//#region src/daemon/proactive-worker.ts
const MAX_CUSTOMERS_PER_CYCLE = 50;
function defaultChannel() {
	if (process.env["TELEGRAM_BOT_TOKEN"] && process.env["TELEGRAM_CHAT_ID"]) return "telegram";
	if (process.env["SLACK_WEBHOOK_URL"]) return "slack";
	return "mcp_tool_response";
}
async function runDailyProactiveChecks(dataDir, today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)) {
	const result = {
		today,
		customersChecked: 0,
		tasksEnqueued: 0,
		errors: []
	};
	const channel = defaultChannel();
	const customersDir = path.join(dataDir, "customers");
	const slugs = fs.existsSync(customersDir) ? fs.readdirSync(customersDir).filter((s) => {
		try {
			return fs.statSync(path.join(customersDir, s)).isDirectory();
		} catch {
			return false;
		}
	}).slice(0, MAX_CUSTOMERS_PER_CYCLE) : [];
	const todayMs = (/* @__PURE__ */ new Date(`${today}T00:00:00Z`)).getTime();
	await Promise.all(slugs.map(async (slug) => {
		try {
			const health = readHealth(dataDir, slug) ?? computeCustomerHealth(dataDir, slug, today);
			for (const contact of health.contacts) if (contact.riskFlags.includes("NO_CONTACT_30D") || contact.grade === "F") {
				await enqueueTask(dataDir, {
					type: "relationship_decay_alert",
					slug,
					priority: contact.grade === "F" ? "urgent" : "high",
					payload: {
						contactId: contact.contactId,
						name: contact.name,
						email: contact.email,
						daysSinceContact: contact.daysSinceContact,
						grade: contact.grade,
						riskFlags: contact.riskFlags
					},
					scheduledFor: (/* @__PURE__ */ new Date()).toISOString(),
					channel
				});
				result.tasksEnqueued++;
			}
			const deals = await readPipeline(dataDir, slug).catch(() => []);
			for (const deal of deals) {
				if (deal.stage === "won" || deal.stage === "lost") continue;
				if (!deal.close_date?.trim()) continue;
				const daysToClose = Math.floor((new Date(deal.close_date).getTime() - todayMs) / 864e5);
				if (daysToClose <= 7) {
					await enqueueTask(dataDir, {
						type: "deal_risk_alert",
						slug,
						priority: daysToClose < 0 ? "urgent" : "high",
						payload: {
							dealName: deal.name,
							stage: deal.stage,
							value: deal.value,
							closeDate: deal.close_date,
							daysToClose,
							overdue: daysToClose < 0
						},
						scheduledFor: (/* @__PURE__ */ new Date()).toISOString(),
						channel
					});
					result.tasksEnqueued++;
				}
			}
			try {
				const factsPath = path.join(dataDir, "customers", slug, "main_facts.md");
				if (fs.existsSync(factsPath)) {
					const raw = fs.readFileSync(factsPath, "utf-8");
					const domainMatch = raw.match(/^domain:\s*(.+)$/im);
					const nameMatch = raw.match(/^name:\s*(.+)$/im);
					const domain = domainMatch?.[1]?.trim();
					const companyName = nameMatch?.[1]?.trim() ?? slug;
					if (domain) {
						const signals = await fetchSignalsForCustomer(dataDir, slug, domain, companyName, today);
						for (const signal of signals) {
							if (signal.impact === "neutral") continue;
							await enqueueTask(dataDir, {
								type: "external_signal_alert",
								slug,
								priority: signal.impact === "negative" ? "urgent" : "high",
								payload: signal,
								scheduledFor: (/* @__PURE__ */ new Date()).toISOString(),
								channel
							});
							result.tasksEnqueued++;
						}
					}
				}
			} catch {}
			result.customersChecked++;
		} catch (err) {
			result.errors.push(`${slug}: ${err.message}`);
		}
	}));
	try {
		await enqueueTask(dataDir, {
			type: "daily_briefing",
			priority: "normal",
			payload: await buildDailyBriefing(dataDir, today),
			scheduledFor: (/* @__PURE__ */ new Date()).toISOString(),
			channel
		});
		result.tasksEnqueued++;
	} catch (err) {
		result.errors.push(`daily_briefing: ${err.message}`);
	}
	runScheduledBackupIfDue(dataDir).catch(() => {});
	return result;
}
//#endregion
export { runDailyProactiveChecks };

//# sourceMappingURL=proactive-worker-1zkm6aJD.js.map