/**
 * olam memory reclassify — operator wrapper over the bridge
 * `/classify/cache-bust` endpoint (Phase B5). Two modes:
 *
 *   $ olam memory reclassify --content-hash=sha256:abc...
 *     # bust one cache entry by content hash
 *
 *   $ olam memory reclassify --since-version=haiku-v1+prompt-v1
 *     # bulk bust by classifier_version (operator-side after a
 *     # prompt-template change)
 *
 *   $ olam memory reclassify --content-hash=sha256:abc... --dry-run
 *     # show what would be busted without calling the bridge
 *
 * Config (env vars):
 *   AGENTMEMORY_BRIDGE_URL    bridge base URL
 *                             (default: https://olam-agent-memory.ernestcodes.workers.dev)
 *   AGENTMEMORY_BRIDGE_SECRET bearer token
 *
 * Plan reference:
 *   docs/plans/agentmemory-classifier-and-regret/phase-b-tasks.md B5
 *   (Originally bundled into B5; carved out as B5.1 because the
 *   bridge endpoint shipped in PR #612 + the CLI is convenience.)
 */
import { printError, printInfo, printHeader, printWarning } from '../../output.js';
const DEFAULT_BRIDGE_URL = 'https://olam-agent-memory.ernestcodes.workers.dev';
const RECLASSIFY_TIMEOUT_MS = 10_000;
/**
 * Validate that the operator supplied EXACTLY one of `--content-hash`
 * or `--since-version`. Returns a clean error string for any malformed
 * input. (Matches the bridge handler's validateCacheBustRequest contract
 * — operator-side errors fail loudly before any HTTP call.)
 */
export function validateReclassifyOptions(opts) {
    const hasHash = typeof opts.contentHash === 'string' && opts.contentHash.length > 0;
    const hasVersion = typeof opts.sinceVersion === 'string' && opts.sinceVersion.length > 0;
    if (!hasHash && !hasVersion) {
        return 'must specify one of --content-hash or --since-version';
    }
    if (hasHash && hasVersion) {
        return '--content-hash and --since-version are mutually exclusive';
    }
    if (hasHash && !/^sha256:[0-9a-f]{64}$/.test(opts.contentHash)) {
        return '--content-hash must be sha256:<64hex>';
    }
    return null;
}
function resolveBridgeUrl(opts) {
    return opts.bridgeUrl
        ?? process.env['AGENTMEMORY_BRIDGE_URL']
        ?? DEFAULT_BRIDGE_URL;
}
function resolveBearer(opts) {
    const fromOpt = opts.bearer;
    if (fromOpt && fromOpt.length > 0)
        return fromOpt;
    const fromEnv = process.env['AGENTMEMORY_BRIDGE_SECRET'];
    if (fromEnv && fromEnv.length > 0)
        return fromEnv;
    return null;
}
/**
 * Run the reclassify call. Pure-ish: takes opts + fetch (so tests can
 * stub) + returns a structured result.
 */
export async function runReclassify(opts, fetchImpl = fetch) {
    const validationError = validateReclassifyOptions(opts);
    if (validationError) {
        return { ok: false, busted: 0, mode: opts.contentHash ? 'hash' : 'version', error: validationError };
    }
    if (opts.dryRun) {
        return {
            ok: true,
            busted: 0,
            mode: 'dry-run',
        };
    }
    const bridgeUrl = resolveBridgeUrl(opts);
    const bearer = resolveBearer(opts);
    if (!bearer) {
        return {
            ok: false,
            busted: 0,
            mode: opts.contentHash ? 'hash' : 'version',
            error: 'AGENTMEMORY_BRIDGE_SECRET not set (or --bearer not passed)',
        };
    }
    const body = opts.contentHash
        ? { content_hash: opts.contentHash }
        : { since_version: opts.sinceVersion };
    try {
        const res = await fetchImpl(`${bridgeUrl}/classify/cache-bust`, {
            method: 'POST',
            headers: {
                authorization: `Bearer ${bearer}`,
                'content-type': 'application/json',
            },
            body: JSON.stringify(body),
            signal: AbortSignal.timeout(RECLASSIFY_TIMEOUT_MS),
        });
        if (!res.ok) {
            const detail = await res.text().catch(() => '');
            return {
                ok: false,
                busted: 0,
                mode: opts.contentHash ? 'hash' : 'version',
                error: `bridge returned ${res.status} ${res.statusText}${detail ? `: ${detail.slice(0, 200)}` : ''}`,
            };
        }
        const payload = (await res.json());
        return {
            ok: true,
            busted: payload.busted,
            mode: payload.mode,
            memoryId: payload.memoryId,
        };
    }
    catch (err) {
        return {
            ok: false,
            busted: 0,
            mode: opts.contentHash ? 'hash' : 'version',
            error: err instanceof Error ? err.message : String(err),
        };
    }
}
/** Run + render. Returns the process exit code. */
export async function runReclassifyCli(opts) {
    const result = await runReclassify(opts);
    if (opts.json) {
        process.stdout.write(JSON.stringify(result, null, 2) + '\n');
        return result.ok ? 0 : 1;
    }
    printHeader('olam memory reclassify');
    if (opts.contentHash) {
        printInfo('content-hash', opts.contentHash);
    }
    if (opts.sinceVersion) {
        printInfo('since-version', opts.sinceVersion);
    }
    printInfo('mode', result.mode);
    if (opts.dryRun) {
        printInfo('dry-run', 'no HTTP call made');
        return 0;
    }
    if (!result.ok) {
        printError(`reclassify failed: ${result.error ?? '(unknown error)'}`);
        return 1;
    }
    if (result.busted === 0) {
        printWarning(`no rows busted (hash not in cache OR no rows matched the version)`);
    }
    else {
        printInfo('busted', `${result.busted}`);
        if (result.memoryId) {
            printInfo('memory-id', result.memoryId);
        }
    }
    return 0;
}
export function registerMemoryReclassify(cmd) {
    cmd
        .command('reclassify')
        .description('Bust the bridge classifier cache (single entry by content hash OR bulk by classifier_version) so the next batch re-runs the LLM')
        .option('--content-hash <hash>', 'Bust one entry by sha256:<64hex> content hash')
        .option('--since-version <version>', 'Bulk bust by classifier_version (e.g. "haiku-v1+prompt-v1")')
        .option('--dry-run', 'Show what would be busted without calling the bridge', false)
        .option('--bridge-url <url>', 'Override AGENTMEMORY_BRIDGE_URL')
        .option('--bearer <token>', 'Override AGENTMEMORY_BRIDGE_SECRET')
        .option('--json', 'Machine-readable JSON output', false)
        .action(async (opts) => {
        const rc = await runReclassifyCli(opts);
        if (rc !== 0)
            process.exitCode = rc;
    });
}
//# sourceMappingURL=reclassify.js.map