/**
 * NERF Adapter — Domain terminology mapping and model routing.
 *
 * Maps NERF's engagement/campaign/task hierarchy to the internal
 * milestone/slice/task project management vocabulary.
 * Provides terminology replacement for user-facing prompts and model routing
 * based on NERF config.yaml phase definitions.
 */
import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { parse as parseYaml } from "yaml";
// ---------------------------------------------------------------------------
// Terminology mapping
// ---------------------------------------------------------------------------
/**
 * NERF domain terminology map.
 * Used to translate between NERF's security engagement vocabulary
 * and the internal project management vocabulary.
 */
const ENGAGEMENT_TO_INTERNAL = {
    engagement: "milestone",
    campaign: "slice",
    // task maps 1:1, no translation needed
};
const INTERNAL_TO_ENGAGEMENT = {
    milestone: "engagement",
    slice: "campaign",
};
/**
 * Map a NERF engagement ID to a NERF milestone ID. NERF uses E001, NERF uses M001.
 *
 */
export function engagementToMilestone(engagementId) {
    const match = engagementId.match(/^E(\d+)/);
    if (!match)
        return engagementId;
    return `M${match[1]}`;
}
/**
 * Map a NERF milestone ID back to a NERF engagement ID.
 */
export function milestoneToEngagement(milestoneId) {
    const match = milestoneId.match(/^M(\d+)/);
    if (!match)
        return milestoneId;
    return `E${match[1]}`;
}
/**
 * Map a NERF campaign ID to a NERF slice ID.
 * NERF uses C01, NERF uses S01.
 */
export function campaignToSlice(campaignId) {
    const match = campaignId.match(/^C(\d+)/);
    if (!match)
        return campaignId;
    return `S${match[1]}`;
}
/**
 * Map a NERF slice ID back to a NERF campaign ID.
 */
export function sliceToCampaign(sliceId) {
    const match = sliceId.match(/^S(\d+)/);
    if (!match)
        return sliceId;
    return `C${match[1]}`;
}
// ---------------------------------------------------------------------------
// Prompt terminology replacement
// ---------------------------------------------------------------------------
/**
 * Replace NERF terminology with NERF terminology in user-facing text.
 * Only replaces whole words to avoid corrupting identifiers like "milestone-summary".
 */
export function nerfizePrompt(text) {
    return text
        .replace(/\bmilestone\b/gi, (m) => matchCase(m, "engagement"))
        .replace(/\bslice\b/gi, (m) => matchCase(m, "campaign"))
        .replace(/\bM(\d{3})\b/g, "E$1")
        .replace(/\bS(\d{2})\b/g, "C$1");
}
/**
 * Replace NERF terminology with NERF terminology.
 */
export function denerfizePrompt(text) {
    return text
        .replace(/\bengagement\b/gi, (m) => matchCase(m, "milestone"))
        .replace(/\bcampaign\b/gi, (m) => matchCase(m, "slice"))
        .replace(/\bE(\d{3})\b/g, "M$1")
        .replace(/\bC(\d{2})\b/g, "S$1");
}
/** Preserve case pattern of the original word in the replacement. */
function matchCase(original, replacement) {
    if (original === original.toUpperCase())
        return replacement.toUpperCase();
    if (original[0] === original[0].toUpperCase()) {
        return replacement[0].toUpperCase() + replacement.slice(1);
    }
    return replacement;
}
let _cachedConfig;
let _cachedConfigCwd = null;
/**
 * Load NERF config.yaml from the project root.
 * Returns null if not found or unparseable.
 */
export function loadNerfConfig() {
    const cwd = process.cwd();
    if (cwd === _cachedConfigCwd && _cachedConfig !== undefined) {
        return _cachedConfig;
    }
    _cachedConfigCwd = cwd;
    const configPath = join(cwd, "config.yaml");
    if (!existsSync(configPath)) {
        _cachedConfig = null;
        return null;
    }
    try {
        const raw = readFileSync(configPath, "utf-8");
        _cachedConfig = parseYaml(raw);
        return _cachedConfig;
    }
    catch {
        _cachedConfig = null;
        return null;
    }
}
/**
 * Get the model ID for a given phase from NERF config.
 * Phases: research, planning, execution, completion.
 */
export function getPhaseModel(phase) {
    const config = loadNerfConfig();
    if (!config?.models)
        return null;
    const entry = config.models[phase];
    if (!entry)
        return null;
    if (typeof entry === "string")
        return entry;
    return entry.model || null;
}
// ---------------------------------------------------------------------------
// Adapter registration
// ---------------------------------------------------------------------------
/**
 * Register NERF adapter hooks.
 * Currently registers model_select for logging phase-aware model routing info.
 */
export function registerNerfAdapter(pi) {
    // Log model selection events with NERF context
    pi.on("model_select", async (event) => {
        const config = loadNerfConfig();
        if (!config?.models)
            return;
        // Informational: log when a model is selected that matches a NERF phase config
        const modelId = event.model?.id;
        if (!modelId)
            return;
        for (const [phase, entry] of Object.entries(config.models)) {
            const phaseModel = typeof entry === "string" ? entry : entry?.model;
            if (phaseModel && modelId.includes(phaseModel.split("/").pop() || "")) {
                process.stderr.write(`[nerf:adapter] Model matches ${phase} phase config: ${modelId}\n`);
                break;
            }
        }
    });
}
