/**
 * CLI telemetry — anonymous usage tracking via PostHog.
 *
 * Sends fire-and-forget events by spawning a detached child process
 * (telemetry-sender.cjs). The parent CLI process exits immediately;
 * the child handles email resolution, caching, and the HTTP POST.
 *
 * Disable with: DEJAVU_TELEMETRY=false
 */

import { spawn } from "node:child_process";
import { createHash, randomUUID } from "node:crypto";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { CONFIG_FILE, loadConfig, saveConfig } from "./config.js";
import { CLI_VERSION } from "./version.js";

const POSTHOG_API_KEY = "phc_hgJkUVJFYtmaJqrvf6CYN67TIQ8yhXAkWzUn9AMU4yX";
const POSTHOG_HOST = "https://us.i.posthog.com/i/v0/e/";

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const SENDER_SCRIPT = path.join(__dirname, "..", "telemetry-sender.cjs");

function isTelemetryEnabled(): boolean {
	try {
		return process.env.DEJAVU_TELEMETRY !== "false";
	} catch {
		return true;
	}
}

/**
 * Return a persistent per-machine anonymous ID, generating one if needed.
 *
 * Stored in ~/.dejavu/config.json under `telemetry.anonymous_id` so that
 * repeat runs on the same machine share one PostHog identity instead of
 * collapsing into a single shared fallback string.
 */
function getOrCreateAnonymousId(): string {
	const config = loadConfig();
	if (config.telemetry.anonymousId) {
		return config.telemetry.anonymousId;
	}

	const newId = `cli-anon-${randomUUID().replace(/-/g, "")}`;
	config.telemetry.anonymousId = newId;
	try {
		saveConfig(config);
	} catch {
		/* ignore persistence failure — still return the generated ID */
	}
	return newId;
}

/**
 * Return a stable anonymous identifier for the current user.
 *
 * Priority: cached user_email (from /v1/ping/) > MD5(api_key) >
 * persistent per-machine anonymous ID.
 */
function getDistinctId(): string {
	try {
		const config = loadConfig();
		if (config.platform.userEmail) {
			return config.platform.userEmail;
		}
		if (config.platform.apiKey) {
			return createHash("md5").update(config.platform.apiKey).digest("hex");
		}
	} catch {
		/* ignore */
	}
	try {
		return getOrCreateAnonymousId();
	} catch {
		return `cli-anon-${randomUUID().replace(/-/g, "")}`;
	}
}

/**
 * Fire a PostHog event (non-blocking, returns void, never throws).
 * Spawns telemetry-sender.cjs as a detached subprocess.
 *
 * When `preResolvedEmail` is provided (e.g. from an upfront ping
 * validation), it is used directly as the PostHog distinct ID and the
 * subprocess skips its own `/v1/ping/` call.
 */
export function captureEvent(
	eventName: string,
	properties: Record<string, unknown> = {},
	preResolvedEmail?: string,
): void {
	if (!isTelemetryEnabled()) return;

	try {
		const config = loadConfig();
		const distinctId = preResolvedEmail || getDistinctId();

		// Detect anonymous → identified transition. If a stored anonymous_id
		// exists and we just resolved to a real identity, fire a one-shot
		// $identify event so PostHog stitches the pre-signup history onto
		// the authenticated profile. Clear the stored id so we don't re-alias.
		let anonIdToAlias: string | null = null;
		if (
			distinctId &&
			!distinctId.startsWith("cli-anon-") &&
			config.telemetry.anonymousId
		) {
			anonIdToAlias = config.telemetry.anonymousId;
			config.telemetry.anonymousId = "";
			try {
				saveConfig(config);
			} catch {
				/* ignore — alias may double-fire next run, harmless */
			}
		}

		// M4: every cli.* event carries agent_mode based on the config flag
		// (unclaimed Agent Mode key). This is the growth-doc property used to
		// join init → add → search funnels in PostHog.
		const payload = {
			api_key: POSTHOG_API_KEY,
			distinct_id: distinctId,
			event: eventName,
			properties: {
				source: "CLI",
				language: "node",
				cli_version: CLI_VERSION,
				agent_mode: Boolean(config.platform.agentMode),
				node_version: process.version,
				os: process.platform,
				...properties,
				$process_person_profile: false,
				$lib: "posthog-node",
			},
		};

		const context = {
			payload,
			posthogHost: POSTHOG_HOST,
			needsEmail: !distinctId || !distinctId.includes("@"),
			dejavuApiKey: config.platform.apiKey || "",
			dejavuBaseUrl: config.platform.baseUrl || "https://api.dejavu.ai",
			configPath: CONFIG_FILE,
			anonDistinctIdToAlias: anonIdToAlias,
		};

		const child = spawn(
			process.execPath,
			[SENDER_SCRIPT, JSON.stringify(context)],
			{ detached: true, stdio: "ignore" },
		);
		child.unref();
	} catch {
		/* silently swallow */
	}
}
