import { i as listCustomerSlugs } from "./customer-dir-CkMMXhb0.js";
import { i as writeJsonFile, n as readJsonFile } from "./json-store-WWsFzXub.js";
import { t as readPipeline } from "./pipeline-writer-CIllfnZl.js";
import { c as readGraph, n as readHealth, s as getStakeholders, t as computeCustomerHealth } from "./relationship-health-ZZNXR1RZ.js";
import path from "path";
//#region src/core/pipeline-stages.ts
const DEFAULT_STAGES = [
	{
		id: "lead",
		label: "Lead",
		order: 1,
		probability: 10
	},
	{
		id: "qualified",
		label: "Qualified",
		order: 2,
		probability: 30
	},
	{
		id: "proposal",
		label: "Proposal",
		order: 3,
		probability: 50
	},
	{
		id: "negotiation",
		label: "Negotiation",
		order: 4,
		probability: 75
	},
	{
		id: "won",
		label: "Won",
		order: 5,
		isFinal: true,
		probability: 100
	},
	{
		id: "lost",
		label: "Lost",
		order: 6,
		isFinal: true,
		probability: 0
	}
];
function stagesPath(dataDir) {
	return path.join(dataDir, ".agentic", "pipeline-stages.json");
}
function getPipelineStages(dataDir) {
	return readJsonFile(stagesPath(dataDir), DEFAULT_STAGES);
}
function setPipelineStage(dataDir, stage) {
	const stages = getPipelineStages(dataDir);
	const idx = stages.findIndex((s) => s.id === stage.id);
	if (idx >= 0) stages[idx] = stage;
	else stages.push(stage);
	stages.sort((a, b) => a.order - b.order);
	writeJsonFile(stagesPath(dataDir), stages);
}
function deletePipelineStage(dataDir, id) {
	writeJsonFile(stagesPath(dataDir), getPipelineStages(dataDir).filter((s) => s.id !== id));
}
function resetToDefaults(dataDir) {
	writeJsonFile(stagesPath(dataDir), DEFAULT_STAGES);
}
//#endregion
//#region src/core/revenue-simulation.ts
function percentile(sorted, p) {
	if (sorted.length === 0) return 0;
	return sorted[Math.max(0, Math.ceil(p / 100 * sorted.length) - 1)];
}
function mean(values) {
	if (values.length === 0) return 0;
	return values.reduce((s, v) => s + v, 0) / values.length;
}
function stdDevFn(values, m) {
	if (values.length < 2) return 0;
	const variance = values.reduce((s, v) => s + (v - m) ** 2, 0) / values.length;
	return Math.sqrt(variance);
}
function adjustProbability(deal, signals = []) {
	let prob = deal.probability / 100;
	const healthAdj = (deal.healthScore - 60) / 100 * .2;
	prob += healthAdj;
	if (deal.championPresent) prob += .05;
	for (const signal of signals) if (signal.slug === deal.slug) {
		if (signal.impact === "positive") prob += .05 * signal.magnitude;
		if (signal.impact === "negative") prob -= .1 * signal.magnitude;
	}
	return Math.max(.02, Math.min(.98, prob));
}
function closeVarianceFn(deal, randFn, todayMs = Date.now()) {
	const variance = (deal.closeDate ? Math.max(0, Math.floor((new Date(deal.closeDate).getTime() - todayMs) / 864e5)) : 90) < 30 ? .05 : .15;
	return 1 + (randFn() - .5) * 2 * variance;
}
function buildSensitivityMap(deals, signals) {
	const map = {};
	for (const deal of deals) map[deal.name] = Math.round(deal.value * adjustProbability(deal, signals));
	return map;
}
function buildTopRisks(deals, signals, sensitivityMap) {
	return deals.filter((d) => d.healthScore < 60 || d.daysSinceContact > 14).sort((a, b) => (sensitivityMap[b.name] ?? 0) - (sensitivityMap[a.name] ?? 0)).slice(0, 5).map((d) => {
		const reasons = [];
		if (d.healthScore < 60) reasons.push(`health ${d.healthScore}`);
		if (d.daysSinceContact > 14) reasons.push(`${d.daysSinceContact}d no contact`);
		if (!d.championPresent) reasons.push("no champion");
		return `${d.slug}/${d.name}: ${reasons.join(", ")} — €${d.value} at risk`;
	});
}
const MAX_ITERATIONS = 5e4;
function runSimulation(input, randFn = Math.random) {
	const { deals, externalSignals } = input;
	const iterations = Math.min(input.iterations, MAX_ITERATIONS);
	if (deals.length === 0) return {
		p10: 0,
		p50: 0,
		p90: 0,
		expected: 0,
		stdDev: 0,
		atRiskRevenue: 0,
		byCloseMonth: {},
		topRisks: [],
		sensitivityMap: {}
	};
	const todayMs = new Date(input.today).getTime();
	const adjustedProbs = deals.map((d) => adjustProbability(d, externalSignals));
	const outcomes = [];
	const byMonthOutcomes = {};
	for (let i = 0; i < iterations; i++) {
		let total = 0;
		const monthTotals = {};
		for (let j = 0; j < deals.length; j++) {
			const deal = deals[j];
			const prob = adjustedProbs[j];
			if (randFn() < prob) {
				const closedValue = Math.round(deal.value * closeVarianceFn(deal, randFn, todayMs));
				total += closedValue;
				if (deal.closeDate) {
					const month = deal.closeDate.slice(0, 7);
					monthTotals[month] = (monthTotals[month] ?? 0) + closedValue;
				}
			}
		}
		outcomes.push(total);
		for (const [month, val] of Object.entries(monthTotals)) if (val > 0) {
			byMonthOutcomes[month] ??= [];
			byMonthOutcomes[month].push(val);
		}
	}
	outcomes.sort((a, b) => a - b);
	const exp = Math.round(mean(outcomes));
	const sd = Math.round(stdDevFn(outcomes, exp));
	const byCloseMonth = {};
	for (const [month, vals] of Object.entries(byMonthOutcomes)) {
		const sorted = [...vals].sort((a, b) => a - b);
		byCloseMonth[month] = {
			p50: Math.round(percentile(sorted, 50)),
			range: [Math.round(percentile(sorted, 10)), Math.round(percentile(sorted, 90))]
		};
	}
	const sensitivityMap = buildSensitivityMap(deals, externalSignals);
	const topRisks = buildTopRisks(deals, externalSignals, sensitivityMap);
	const atRiskRevenue = deals.filter((d) => d.healthScore < 60).reduce((s, d) => s + d.value, 0);
	return {
		p10: Math.round(percentile(outcomes, 10)),
		p50: Math.round(percentile(outcomes, 50)),
		p90: Math.round(percentile(outcomes, 90)),
		expected: exp,
		stdDev: sd,
		atRiskRevenue,
		byCloseMonth,
		topRisks,
		sensitivityMap
	};
}
function buildConfidenceMessage(result, dealCount) {
	const range = result.p90 - result.p10;
	const atRiskPct = result.expected > 0 ? Math.round(result.atRiskRevenue / result.expected * 100) : 0;
	return `P50 forecast: €${(result.p50 / 1e3).toFixed(1)}k with ±€${(range / 2 / 1e3).toFixed(1)}k uncertainty (P10–P90 range). ${atRiskPct}% of pipeline is at risk. ${dealCount} deals simulated.`;
}
function getQuarterEnd(date) {
	const month = date.getMonth();
	const quarterEndMonth = Math.floor(month / 3) * 3 + 2;
	return new Date(date.getFullYear(), quarterEndMonth + 1, 0);
}
async function buildSimulationInput(dataDir, horizon, today, externalSignals = []) {
	const slugs = listCustomerSlugs(dataDir);
	if (slugs.length === 0) return {
		deals: [],
		externalSignals,
		iterations: 1e4,
		horizon,
		today
	};
	const stages = getPipelineStages(dataDir);
	const stageProb = {};
	for (const s of stages) stageProb[s.id] = s.probability ?? 50;
	const deals = [];
	const todayDate = new Date(today);
	const horizonEnd = horizon === "quarter" ? getQuarterEnd(todayDate) : new Date(todayDate.getFullYear(), 11, 31);
	for (const slug of slugs) {
		const pipelineDeals = await readPipeline(dataDir, slug).catch(() => []);
		if (pipelineDeals.length === 0) continue;
		const health = readHealth(dataDir, slug) ?? computeCustomerHealth(dataDir, slug, today);
		const healthScore = health.overallHealth;
		const championPresent = getStakeholders(readGraph(dataDir, slug)).champions.length > 0;
		const lastContact = health.contacts.map((c) => c.lastContact).filter((lc) => !!lc).sort().pop();
		const daysSinceContact = lastContact ? Math.floor((todayDate.getTime() - new Date(lastContact).getTime()) / 864e5) : 999;
		for (const deal of pipelineDeals) {
			if (deal.stage === "won" || deal.stage === "lost") continue;
			if (deal.close_date && deal.close_date.trim() !== "") {
				if (new Date(deal.close_date) > horizonEnd) continue;
			}
			const probability = deal.probability ?? stageProb[deal.stage] ?? 50;
			const snapshot = {
				slug,
				name: deal.name,
				stage: deal.stage,
				value: deal.value ?? 0,
				probability,
				healthScore,
				daysSinceContact,
				championPresent
			};
			if (deal.close_date && deal.close_date.trim() !== "") snapshot.closeDate = deal.close_date;
			deals.push(snapshot);
		}
	}
	return {
		deals,
		externalSignals,
		iterations: 1e4,
		horizon,
		today
	};
}
//#endregion
export { buildTopRisks as a, percentile as c, deletePipelineStage as d, getPipelineStages as f, buildSimulationInput as i, runSimulation as l, setPipelineStage as m, buildConfidenceMessage as n, closeVarianceFn as o, resetToDefaults as p, buildSensitivityMap as r, mean as s, adjustProbability as t, stdDevFn as u };

//# sourceMappingURL=revenue-simulation-D8f_YkUY.js.map