/**
 * Reasoning Assist — Pre-stage expert consultation for SF units.
 *
 * Purpose: Before dispatching a unit, call a faster/cheaper model to read
 * context and write strategic guidance. Injects guidance into the unit prompt.
 *
 * Consumer: auto-loop dispatch path, before each unit type.
 *
 * Design:
 * - Optional: enabled via preferences or explicit flag
 * - Uses a cheaper model (fast tier) for cost efficiency
 * - Reads project context, decisions, requirements, prior summaries
 * - Writes 1-5 paragraphs of step-by-step guidance
 * - Injects as "expert guidance" section into prompt
 */

import { getAutoSession } from "./auto/session.js";
import { loadFile } from "./files.js";
import {
	formatMemoriesForPrompt,
	getMemories,
	MEMORY_TYPES,
} from "./memory-repository.js";
import {
	resolveMilestoneFile,
	resolveSfRootFile,
	resolveSliceFile,
} from "./paths.js";
import { logWarning } from "./workflow-logger.js";

const REASONING_ASSIST_ENABLED = process.env.SF_REASONING_ASSIST === "1";
const REASONING_ASSIST_MAX_CHARS = 2000;

/**
 * Build a reasoning assist prompt for a given unit type.
 *
 * @param {string} unitType — e.g. "research-slice", "plan-slice", "execute-task"
 * @param {string} unitId — e.g. "M001/S01/T01"
 * @param {string} basePath — project root
 * @param {object} ctx — dispatch context
 * @returns {string|null} — reasoning prompt or null if disabled
 */
export async function buildReasoningAssistPrompt(
	unitType,
	unitId,
	basePath,
	ctx,
) {
	if (!REASONING_ASSIST_ENABLED) return null;

	const parts = [];
	parts.push(
		`You are a senior engineering advisor. The team is about to run a "${unitType}" unit (${unitId}).`,
	);
	parts.push(
		"Review the available context and write 3-5 sentences of strategic guidance:",
	);
	parts.push("- What should the agent focus on?");
	parts.push("- What common mistakes should it avoid?");
	parts.push("- What tools should it use and in what order?");
	parts.push("- Any specific files or patterns to pay attention to?");
	parts.push("Be concise. Do not write code. Do not expand scope.");
	parts.push("");

	// Load relevant context files
	const contextFiles = await loadRelevantContext(
		unitType,
		unitId,
		basePath,
		ctx,
	);
	for (const { label, content } of contextFiles) {
		if (content) {
			parts.push(`--- ${label} ---`);
			parts.push(content.slice(0, 1500));
			parts.push("");
		}
	}

	const result = parts.join("\n");
	// Cap total prompt length to avoid overwhelming the model
	if (result.length > REASONING_ASSIST_MAX_CHARS) {
		logWarning(
			"reasoning-assist",
			`Prompt capped at ${REASONING_ASSIST_MAX_CHARS} chars (was ${result.length})`,
		);
		return result.slice(0, REASONING_ASSIST_MAX_CHARS);
	}
	return result;
}

async function loadRelevantContext(unitType, unitId, basePath, ctx) {
	const results = [];

	// Parse unit ID
	const segments = unitId.split("/");
	const milestoneId = segments[0];
	const sliceId = segments[1];

	// Load structured memory (RA.Aid-style key facts/snippets/notes)
	const sessionId = ctx?.sessionManager?.getSessionId?.();
	if (sessionId) {
		const { getDatabase } = await import("./sf-db.js");
		const db = getDatabase();

		// Key facts
		const keyFacts = getMemories({
			sessionId,
			type: MEMORY_TYPES.KEY_FACT,
			limit: 20,
			db,
		});
		if (keyFacts.length > 0) {
			const formatted = formatMemoriesForPrompt(keyFacts, {
				header: "Key Facts:",
				maxChars: 1500,
			});
			if (formatted) results.push({ label: "Key Facts", content: formatted });
		}

		// Key snippets for implementation
		if (unitType.includes("execute") || unitType.includes("implement")) {
			const snippets = getMemories({
				sessionId,
				type: MEMORY_TYPES.KEY_SNIPPET,
				limit: 10,
				db,
			});
			if (snippets.length > 0) {
				const formatted = formatMemoriesForPrompt(snippets, {
					header: "Key Snippets:",
					maxChars: 2000,
				});
				if (formatted)
					results.push({ label: "Key Snippets", content: formatted });
			}
		}

		// Research notes for research/planning
		if (unitType.includes("research") || unitType.includes("plan")) {
			const notes = getMemories({
				sessionId,
				type: MEMORY_TYPES.RESEARCH_NOTE,
				limit: 10,
				db,
			});
			if (notes.length > 0) {
				const formatted = formatMemoriesForPrompt(notes, {
					header: "Research Notes:",
					maxChars: 2000,
				});
				if (formatted)
					results.push({ label: "Research Notes", content: formatted });
			}
		}
	}

	// Load decisions
	const decisionsPath = resolveSfRootFile(basePath, "DECISIONS");
	if (decisionsPath) {
		const content = await loadFile(decisionsPath);
		if (content) results.push({ label: "Decisions", content });
	}

	// Load requirements
	const requirementsPath = resolveSfRootFile(basePath, "REQUIREMENTS");
	if (requirementsPath) {
		const content = await loadFile(requirementsPath);
		if (content) results.push({ label: "Requirements", content });
	}

	// Load milestone context
	if (milestoneId) {
		const contextPath = resolveMilestoneFile(basePath, milestoneId, "CONTEXT");
		if (contextPath) {
			const content = await loadFile(contextPath);
			if (content)
				results.push({ label: `Milestone ${milestoneId} Context`, content });
		}
	}

	// Load slice research for planning/execution
	if (sliceId && (unitType.includes("plan") || unitType.includes("execute"))) {
		const researchPath = resolveSliceFile(
			basePath,
			milestoneId,
			sliceId,
			"RESEARCH",
		);
		if (researchPath) {
			const content = await loadFile(researchPath);
			if (content)
				results.push({ label: `Slice ${sliceId} Research`, content });
		}
	}

	return results;
}

/**
 * Inject reasoning assist guidance into a prompt.
 *
 * @param {string} prompt — original prompt
 * @param {string} guidance — reasoning assist output
 * @returns {string} — prompt with guidance injected
 */
export function injectReasoningGuidance(prompt, guidance) {
	if (!guidance || guidance.trim().length === 0) return prompt;
	const section = `
## Expert Guidance

${guidance.trim()}

Follow this guidance when executing the unit. If the guidance conflicts with
explicit instructions elsewhere, prefer the explicit instructions but note the
discrepancy.
`;
	// Insert before the first "##" heading if present, otherwise append
	const firstHeading = prompt.indexOf("\n##");
	if (firstHeading > 0) {
		return prompt.slice(0, firstHeading) + section + prompt.slice(firstHeading);
	}
	return prompt + section;
}

/**
 * Check if reasoning assist is enabled for a unit type.
 */
export function isReasoningAssistEnabled(unitType) {
	if (!REASONING_ASSIST_ENABLED) return false;
	// Respect auto session mode — don't assist when paused
	const autoSession = getAutoSession();
	if (autoSession && !autoSession.isRunning()) {
		logWarning("reasoning-assist", "Skipping: auto session not running");
		return false;
	}
	// Only enable for complex unit types
	const enabledTypes = [
		"research-milestone",
		"research-slice",
		"plan-milestone",
		"plan-slice",
		"execute-task",
		"complete-slice",
		"complete-milestone",
	];
	return enabledTypes.includes(unitType);
}
