// ─────────────────────────────────────────────────────────────────────────────
// Nexus Prime Licensing — Enforcement Middleware
//
// Plugs into the NexusMiddleware pipeline at priority 5 (runs before all
// built-in middleware). Checks tool tier access and quantity caps.
//
// Enforcement modes (NEXUS_ENFORCEMENT_MODE env var):
//   audit — log only, never block (default during grace period)
//   soft  — warn in response, still execute (default after grace)
//   hard  — block caps at 100%, soft-block tool tiers
// ─────────────────────────────────────────────────────────────────────────────
import { getSharedLicenseManager } from './license-manager.js';
import { getToolTier, isToolAllowed } from './tool-tiers.js';
import { toolGateMessage, capWarningMessage, capExceededMessage, noLicenseMessage, trialActiveMessage, trialExpiredMessage, } from './upgrade-prompts.js';
function getMode() {
    const val = (process.env.NEXUS_ENFORCEMENT_MODE ?? 'soft').toLowerCase();
    if (val === 'audit' || val === 'hard')
        return val;
    return 'soft';
}
// Tools that create resources subject to quantity caps
const MEMORY_CREATION_TOOLS = new Set(['nexus_store_memory']);
const OPERATIVE_CREATION_TOOLS = new Set(['nexus_synapse_hire', 'nexus_synapse_mandate']);
const LICENSE_SAFE_TOOLS = new Set([
    'nexus_license_usage',
    'nexus_runtime_health',
    'nexus_describe_tool',
    'nexus_session_dna',
]);
/**
 * LicenseEnforcementMiddleware — priority 5 (runs first in the pipeline).
 *
 * before(): checks tool tier + quantity caps
 * after(): appends upgrade hints to tool responses
 */
export const LicenseEnforcementMiddleware = {
    name: 'license-enforcement',
    priority: 5,
    before(ctx) {
        const lm = getSharedLicenseManager();
        const status = lm.getStatus();
        const mode = getMode();
        const toolName = ctx.toolName;
        // Keep activation/status paths available even when the trial gate is closed.
        if (LICENSE_SAFE_TOOLS.has(toolName))
            return;
        // ── No license check ──────────────────────────────────────────────
        if (status.degradedReason === 'not-activated') {
            if (mode !== 'audit') {
                ctx.meta.licenseUpgradeHint = noLicenseMessage();
            }
            // In all modes: let the tool execute (soft gate during ramp)
            return;
        }
        if (status.degradedReason === 'activation-required') {
            const msg = trialActiveMessage(status);
            if (mode !== 'audit') {
                ctx.meta.licenseUpgradeHint = msg;
            }
            return;
        }
        if (status.degradedReason === 'trial-expired') {
            const msg = trialExpiredMessage();
            if (mode !== 'audit') {
                ctx.meta.shortCircuitResult = {
                    content: [{ type: 'text', text: msg }],
                };
                ctx.meta.shortCircuitedBy = 'license-enforcement';
            }
            return;
        }
        if (status.trial && mode !== 'audit') {
            // Soft footer so users know the runtime is being kept alive by the
            // auto-issued local trial. Doesn't gate execution — paid tiers behave
            // exactly like a real license while the trial is active.
            ctx.meta.licenseUpgradeHint = trialActiveMessage(status);
        }
        // ── Tool tier check ───────────────────────────────────────────────
        if (!isToolAllowed(toolName, status.tier)) {
            const requiredTier = getToolTier(toolName);
            const msg = toolGateMessage(toolName, requiredTier, status.tier);
            if (mode === 'hard') {
                ctx.meta.shortCircuitResult = {
                    content: [{ type: 'text', text: msg }],
                };
                ctx.meta.shortCircuitedBy = 'license-enforcement';
                return;
            }
            // soft/audit: tag for after() to append
            ctx.meta.licenseUpgradeHint = msg;
        }
        // ── Quantity cap checks ───────────────────────────────────────────
        let capResult = null;
        let capType = '';
        if (MEMORY_CREATION_TOOLS.has(toolName)) {
            // Read memory count from args or meta if available
            const memCount = ctx.meta.currentMemoryCount ?? 0;
            capResult = lm.checkCap('memory_entries', memCount);
            capType = 'memory_entries';
        }
        else if (OPERATIVE_CREATION_TOOLS.has(toolName)) {
            const opCount = ctx.meta.currentOperativeCount ?? 0;
            capResult = lm.checkCap('operatives', opCount);
            capType = 'operatives';
        }
        if (capResult) {
            if (capResult.exceeded) {
                const msg = capExceededMessage(capResult, capType);
                if (mode === 'hard') {
                    ctx.meta.shortCircuitResult = {
                        content: [{ type: 'text', text: msg }],
                    };
                    ctx.meta.shortCircuitedBy = 'license-enforcement';
                    return;
                }
                ctx.meta.licenseUpgradeHint = msg;
            }
            else if (capResult.warning) {
                ctx.meta.licenseUpgradeHint = capWarningMessage(capResult, capType);
            }
        }
    },
    after(ctx, result) {
        const hint = ctx.meta.licenseUpgradeHint;
        if (hint && result.content) {
            result.content.push({ type: 'text', text: `\n---\n${hint}` });
        }
    },
};
