import { readFile, writeFile, mkdir, readdir } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { existsSync } from "node:fs";
// In-memory plan registry
const activePlans = new Map();
function generateId() {
    return `plan_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
}
/**
 * Create a new analysis plan with a scratchpad directory.
 */
export async function createAnalysisPlan(title, steps) {
    const id = generateId();
    const scratchpadDir = join(tmpdir(), "codesift-scratchpad", id);
    await mkdir(scratchpadDir, { recursive: true });
    const plan = {
        id,
        title,
        steps: steps.map((s, i) => ({
            id: `step_${i + 1}`,
            description: s.description,
            tool: s.tool,
            args: s.args,
            status: "pending",
            ...(s.result_key ? { result_key: s.result_key } : {}),
            ...(s.depends_on ? { depends_on: s.depends_on } : {}),
        })),
        status: "pending",
        scratchpad_dir: scratchpadDir,
        created_at: new Date().toISOString(),
    };
    activePlans.set(id, plan);
    // Write plan metadata to scratchpad
    await writeFile(join(scratchpadDir, "_plan.json"), JSON.stringify(plan, null, 2), "utf-8");
    return plan;
}
/**
 * Write a key-value entry to the plan's scratchpad.
 * Scratchpad entries are persisted as individual files.
 */
export async function writeScratchpad(planId, key, value) {
    const plan = activePlans.get(planId);
    if (!plan)
        throw new Error(`Plan "${planId}" not found`);
    // Sanitize key for filesystem
    const safeKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
    const now = new Date().toISOString();
    const entry = {
        key,
        value,
        created_at: now,
        updated_at: now,
    };
    await writeFile(join(plan.scratchpad_dir, `${safeKey}.json`), JSON.stringify(entry, null, 2), "utf-8");
    return entry;
}
/**
 * Read a key from the plan's scratchpad.
 */
export async function readScratchpad(planId, key) {
    const plan = activePlans.get(planId);
    if (!plan)
        throw new Error(`Plan "${planId}" not found`);
    const safeKey = key.replace(/[^a-zA-Z0-9_-]/g, "_");
    const filePath = join(plan.scratchpad_dir, `${safeKey}.json`);
    try {
        const content = await readFile(filePath, "utf-8");
        return JSON.parse(content);
    }
    catch {
        return null;
    }
}
/**
 * List all entries in the plan's scratchpad.
 */
export async function listScratchpad(planId) {
    const plan = activePlans.get(planId);
    if (!plan)
        throw new Error(`Plan "${planId}" not found`);
    if (!existsSync(plan.scratchpad_dir)) {
        return { entries: [] };
    }
    const files = await readdir(plan.scratchpad_dir);
    const entries = [];
    for (const file of files) {
        if (file.startsWith("_") || !file.endsWith(".json"))
            continue;
        try {
            const content = await readFile(join(plan.scratchpad_dir, file), "utf-8");
            const entry = JSON.parse(content);
            entries.push({
                key: entry.key,
                size: entry.value.length,
                updated_at: entry.updated_at,
            });
        }
        catch {
            // Skip corrupt entries
        }
    }
    return { entries };
}
/**
 * Update a step's status in the plan.
 */
export async function updateStepStatus(planId, stepId, status, error) {
    const plan = activePlans.get(planId);
    if (!plan)
        throw new Error(`Plan "${planId}" not found`);
    const step = plan.steps.find((s) => s.id === stepId);
    if (!step)
        throw new Error(`Step "${stepId}" not found in plan "${planId}"`);
    step.status = status;
    if (error)
        step.error = error;
    // Update plan status
    const allDone = plan.steps.every((s) => s.status === "completed" || s.status === "skipped");
    const anyFailed = plan.steps.some((s) => s.status === "failed");
    if (allDone) {
        plan.status = "completed";
        plan.completed_at = new Date().toISOString();
    }
    else if (anyFailed) {
        plan.status = "failed";
    }
    else {
        plan.status = "in_progress";
    }
    // Persist updated plan
    await writeFile(join(plan.scratchpad_dir, "_plan.json"), JSON.stringify(plan, null, 2), "utf-8");
    return plan;
}
/**
 * Get the current state of a plan.
 */
export function getPlan(planId) {
    return activePlans.get(planId) ?? null;
}
/**
 * List all active plans.
 */
export function listPlans() {
    return Array.from(activePlans.values()).map((p) => ({
        id: p.id,
        title: p.title,
        status: p.status,
        steps_completed: p.steps.filter((s) => s.status === "completed").length,
        steps_total: p.steps.length,
    }));
}
//# sourceMappingURL=coordinator-tools.js.map