import { existsSync } from "node:fs";
import { join, sep } from "node:path";
import { createBashTool, createEditTool, createReadTool, createWriteTool } from "@nerf/pi-coding-agent";
import { DEFAULT_BASH_TIMEOUT_SECS } from "../constants.js";
import { setLogBasePath } from "../workflow-logger.js";
/**
 * Resolve the correct DB path for the current working directory.
 * If `basePath` is inside a `.nerf/worktrees/<MID>/` directory, returns
 * the project root's `.nerf/nerf.db` (shared WAL — R012). Otherwise
 * returns `<basePath>/.nerf/nerf.db`.
 */
export function resolveProjectRootDbPath(basePath) {
    // Detect worktree: look for `.nerf/worktrees/` or legacy `.nerf/worktrees/` in the path segments.
    // A worktree path looks like: /project/root/.nerf/worktrees/M001/...
    // We need to resolve back to /project/root/.nerf/nerf.db
    for (const dir of [".nerf", ".nerf"]) {
        const marker = `${sep}${dir}${sep}worktrees${sep}`;
        const idx = basePath.indexOf(marker);
        if (idx !== -1) {
            const projectRoot = basePath.slice(0, idx);
            return join(projectRoot, ".nerf", "nerf.db");
        }
        // Also handle forward-slash paths on all platforms
        const fwdMarker = `/${dir}/worktrees/`;
        const fwdIdx = basePath.indexOf(fwdMarker);
        if (fwdIdx !== -1) {
            const projectRoot = basePath.slice(0, fwdIdx);
            return join(projectRoot, ".nerf", "nerf.db");
        }
    }
    return join(basePath, ".nerf", "nerf.db");
}
export async function ensureDbOpen() {
    try {
        const db = await import("../nerf-db.js");
        if (db.isDbAvailable())
            return true;
        const basePath = process.cwd();
        const dbPath = resolveProjectRootDbPath(basePath);
        const nerfDir = join(basePath, ".nerf");
        // Derive the project root from the DB path (strip .nerf/nerf.db)
        const projectRoot = join(dbPath, "..", "..");
        // Open existing DB file (may be at project root for worktrees)
        if (existsSync(dbPath)) {
            const opened = db.openDatabase(dbPath);
            if (opened)
                setLogBasePath(projectRoot);
            return opened;
        }
        // No DB file — create + migrate from Markdown if .nerf/ has content
        if (existsSync(nerfDir)) {
            const hasDecisions = existsSync(join(nerfDir, "DECISIONS.md"));
            const hasRequirements = existsSync(join(nerfDir, "REQUIREMENTS.md"));
            const hasMilestones = existsSync(join(nerfDir, "milestones"));
            if (hasDecisions || hasRequirements || hasMilestones) {
                const opened = db.openDatabase(dbPath);
                if (opened) {
                    setLogBasePath(projectRoot);
                    try {
                        const { migrateFromMarkdown } = await import("../md-importer.js");
                        migrateFromMarkdown(basePath);
                    }
                    catch (err) {
                        process.stderr.write(`nerf-db: ensureDbOpen auto-migration failed: ${err.message}\n`);
                    }
                }
                return opened;
            }
            // .nerf/ exists but has no Markdown content (fresh project) — create empty DB
            const opened = db.openDatabase(dbPath);
            if (opened)
                setLogBasePath(projectRoot);
            return opened;
        }
        return false;
    }
    catch {
        return false;
    }
}
export function registerDynamicTools(pi) {
    const baseBash = createBashTool(process.cwd(), {
        spawnHook: (ctx) => ({ ...ctx, cwd: process.cwd() }),
    });
    const dynamicBash = {
        ...baseBash,
        execute: async (toolCallId, params, signal, onUpdate, ctx) => {
            const paramsWithTimeout = {
                ...params,
                timeout: params.timeout ?? DEFAULT_BASH_TIMEOUT_SECS,
            };
            return baseBash.execute(toolCallId, paramsWithTimeout, signal, onUpdate, ctx);
        },
    };
    pi.registerTool(dynamicBash);
    const baseWrite = createWriteTool(process.cwd());
    pi.registerTool({
        ...baseWrite,
        execute: async (toolCallId, params, signal, onUpdate, ctx) => {
            const fresh = createWriteTool(process.cwd());
            return fresh.execute(toolCallId, params, signal, onUpdate, ctx);
        },
    });
    const baseRead = createReadTool(process.cwd());
    pi.registerTool({
        ...baseRead,
        execute: async (toolCallId, params, signal, onUpdate, ctx) => {
            const fresh = createReadTool(process.cwd());
            return fresh.execute(toolCallId, params, signal, onUpdate, ctx);
        },
    });
    const baseEdit = createEditTool(process.cwd());
    pi.registerTool({
        ...baseEdit,
        execute: async (toolCallId, params, signal, onUpdate, ctx) => {
            const fresh = createEditTool(process.cwd());
            return fresh.execute(toolCallId, params, signal, onUpdate, ctx);
        },
    });
}
