/**
 * `olam kg install-hook [--scope project|user] [--for claude|hermes]`
 *
 * Default (--for claude, --scope project): wire the kg-service PreToolUse
 * hook into .claude/settings.json.
 *
 * --for hermes: install kg-first.sh into ~/.hermes/hooks/ and patch
 * ~/.hermes/config.yaml hooks.pre_tool_call. Refuses if
 * ~/.hermes/config.yaml doesn't exist.
 *
 * Default scope=project writes to `<cwd>/.claude/settings.json`. Per-repo
 * opt-in keeps blast radius small (operator can try it on one repo before
 * promoting to --scope user which targets `~/.claude/settings.json`).
 *
 * Idempotent via mergeHomeSettingsJson + the KG_HOOK_SENTINEL marker in
 * the command string. Re-running over an existing install is a no-op.
 */
import * as fs from 'node:fs';
import * as path from 'node:path';
import * as os from 'node:os';
import { parse as yamlParse, stringify as yamlStringify } from 'yaml';
import { mergeHomeSettingsJson } from '@olam/core/src/world/merge-settings.js';
import { buildHookMatcherEntry, KG_HOOK_SENTINEL, } from '@olam/core/src/kg/hook-template.js';
import { printError, printInfo, printSuccess, printWarning } from '../output.js';
import { installKgFirstHookForHermes, HERMES_KG_HOOK_SENTINEL, } from './hermes-kg-hook.js';
function settingsPathFor(scope) {
    if (scope === 'user') {
        return path.join(os.homedir(), '.claude', 'settings.json');
    }
    return path.join(process.cwd(), '.claude', 'settings.json');
}
function backup(filePath) {
    if (!fs.existsSync(filePath))
        return null;
    const ts = new Date().toISOString().replace(/[:.]/g, '-');
    const backupPath = `${filePath}.olam-bak.${ts}`;
    fs.copyFileSync(filePath, backupPath);
    return backupPath;
}
const HERMES_HOOK_MATCHERS = ['terminal', 'bash', 'shell', 'search_files', 'grep', 'ripgrep'];
function hermesConfigPath() {
    return path.join(os.homedir(), '.hermes', 'config.yaml');
}
function hermesHooksDir() {
    return path.join(os.homedir(), '.hermes', 'hooks');
}
/**
 * Patch ~/.hermes/config.yaml to add / remove the pre_tool_call entry.
 * Idempotent: checks for HERMES_KG_HOOK_SENTINEL before writing.
 */
function patchHermesConfigForHook(action) {
    const configPath = hermesConfigPath();
    const raw = fs.readFileSync(configPath, 'utf-8');
    const config = yamlParse(raw);
    const hooks = (config['hooks'] ?? {});
    const preToolCall = Array.isArray(hooks['pre_tool_call'])
        ? hooks['pre_tool_call']
        : [];
    if (action === 'install') {
        const alreadyPresent = preToolCall.some((e) => typeof e['command'] === 'string' && e['command'].includes(HERMES_KG_HOOK_SENTINEL));
        if (alreadyPresent)
            return 'already-present';
        const hookScriptPath = path.join(hermesHooksDir(), 'kg-first.sh');
        const entry = {
            matcher: HERMES_HOOK_MATCHERS.join('|'),
            command: `${hookScriptPath} # ${HERMES_KG_HOOK_SENTINEL}`,
        };
        const updated = {
            ...config,
            hooks: { ...hooks, pre_tool_call: [...preToolCall, entry] },
            hooks_auto_accept: true,
        };
        fs.writeFileSync(configPath, yamlStringify(updated), 'utf-8');
        return 'patched';
    }
    // uninstall
    const filtered = preToolCall.filter((e) => !(typeof e['command'] === 'string' && e['command'].includes(HERMES_KG_HOOK_SENTINEL)));
    if (filtered.length === preToolCall.length)
        return 'already-absent';
    const updated = {
        ...config,
        hooks: { ...hooks, pre_tool_call: filtered },
    };
    fs.writeFileSync(configPath, yamlStringify(updated), 'utf-8');
    return 'patched';
}
// ── Action: install for Hermes ────────────────────────────────────────────────
function doInstallForHermes() {
    const configPath = hermesConfigPath();
    if (!fs.existsSync(configPath)) {
        printError(`~/.hermes/config.yaml not found at ${configPath}`);
        printInfo('remedy', 'Install Hermes first, then re-run `olam kg install-hook --for hermes`');
        process.exitCode = 1;
        return;
    }
    const hooksDir = hermesHooksDir();
    const hookResult = installKgFirstHookForHermes(hooksDir, /* dryRun */ false);
    const configResult = patchHermesConfigForHook('install');
    if (hookResult.status === 'already-present' && configResult === 'already-present') {
        printInfo('kg-first hook', `already installed for Hermes`);
        return;
    }
    if (hookResult.status === 'installed') {
        printSuccess(`kg-first.sh installed → ${hookResult.destPath}`);
    }
    if (configResult === 'patched') {
        printSuccess(`${configPath} patched — hooks.pre_tool_call entry added`);
    }
    printInfo('next', 'hermes gateway restart');
}
// ── Action: uninstall for Hermes ──────────────────────────────────────────────
function doUninstallForHermes() {
    const configPath = hermesConfigPath();
    const hooksDir = hermesHooksDir();
    const hookScriptPath = path.join(hooksDir, 'kg-first.sh');
    let scriptRemoved = false;
    if (fs.existsSync(hookScriptPath)) {
        const content = fs.readFileSync(hookScriptPath, 'utf-8');
        if (content.includes(HERMES_KG_HOOK_SENTINEL)) {
            fs.unlinkSync(hookScriptPath);
            scriptRemoved = true;
        }
    }
    let configPatched = false;
    if (fs.existsSync(configPath)) {
        const result = patchHermesConfigForHook('uninstall');
        configPatched = result === 'patched';
    }
    if (!scriptRemoved && !configPatched) {
        printInfo('kg-first hook', 'not installed for Hermes — nothing to remove');
        return;
    }
    if (scriptRemoved)
        printSuccess(`kg-first.sh removed from ${hooksDir}`);
    if (configPatched)
        printSuccess(`${configPath} patched — pre_tool_call entry removed`);
}
// ── Command registration ──────────────────────────────────────────────────────
export function registerKgInstallHookCommand(kg) {
    kg.command('install-hook')
        .description('Install kg-service hook (idempotent). --for hermes targets ~/.hermes/; default targets .claude/settings.json')
        .option('--scope <scope>', 'project (default; <cwd>/.claude/settings.json) or user (~/.claude/settings.json)', 'project')
        .option('--for <target>', 'Target agent: claude (default) or hermes', 'claude')
        .option('--uninstall', 'Uninstall instead of install')
        .action((opts) => {
        const target = opts.for === 'hermes' ? 'hermes' : 'claude';
        if (target === 'hermes') {
            if (opts.uninstall) {
                doUninstallForHermes();
            }
            else {
                doInstallForHermes();
            }
            return;
        }
        // ── Claude target (original behaviour) ──────────────────────────────
        const scope = opts.scope === 'user' ? 'user' : 'project';
        const filePath = settingsPathFor(scope);
        try {
            fs.mkdirSync(path.dirname(filePath), { recursive: true });
        }
        catch (err) {
            printError(`could not create ${path.dirname(filePath)}: ${err instanceof Error ? err.message : String(err)}`);
            process.exitCode = 1;
            return;
        }
        const backupPath = backup(filePath);
        try {
            const result = mergeHomeSettingsJson(filePath, {
                ensureHook: {
                    stage: 'PreToolUse',
                    sentinel: KG_HOOK_SENTINEL,
                    entry: buildHookMatcherEntry({ flavor: 'host' }),
                },
            });
            switch (result.status) {
                case 'installed':
                    printSuccess(`kg-service hook installed (${scope} scope)`);
                    printInfo('settings', filePath);
                    if (backupPath)
                        printInfo('backup', backupPath);
                    printInfo('next', 'open a new Claude Code session in this directory; grep/find tool calls will now be routed via kg-service');
                    return;
                case 'already-present':
                    printInfo('kg-service hook', `already installed at ${filePath}`);
                    if (backupPath) {
                        try {
                            fs.unlinkSync(backupPath);
                        }
                        catch {
                            // best-effort
                        }
                    }
                    return;
                case 'no-op':
                    printWarning(`no change made to ${filePath}`);
                    return;
            }
        }
        catch (err) {
            printError(`install-hook failed: ${err instanceof Error ? err.message : String(err)}`);
            if (backupPath)
                printInfo('backup', `settings.json preserved at ${backupPath}`);
            process.exitCode = 1;
        }
    });
}
//# sourceMappingURL=kg-install-hook.js.map