import fs from 'node:fs/promises';
import path from 'node:path';
import { readJsonFile, writeJsonFileAtomic } from './clock/io.js';
function readSessionDirEnv() {
    return String(process.env.ROUTECODEX_SESSION_DIR || '').trim();
}
function sanitizeSegment(value) {
    return String(value || '')
        .trim()
        .replace(/[^a-zA-Z0-9_.-]/g, '_')
        .replace(/_+/g, '_')
        .replace(/^_+|_+$/g, '');
}
function resolvePendingDir(sessionDir) {
    return path.join(sessionDir, 'servertool-pending');
}
function resolvePendingFile(sessionDir, sessionId) {
    const safe = sanitizeSegment(sessionId);
    if (!safe)
        return null;
    return path.join(resolvePendingDir(sessionDir), `${safe}.json`);
}
function coercePending(value) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        return null;
    }
    const rec = value;
    const sessionId = typeof rec.sessionId === 'string' ? rec.sessionId.trim() : '';
    const createdAtMs = typeof rec.createdAtMs === 'number' && Number.isFinite(rec.createdAtMs) ? Math.floor(rec.createdAtMs) : 0;
    const afterToolCallIds = Array.isArray(rec.afterToolCallIds)
        ? rec.afterToolCallIds.filter((x) => typeof x === 'string' && x.trim().length).map((x) => String(x).trim())
        : [];
    const messages = Array.isArray(rec.messages)
        ? rec.messages.filter((m) => m && typeof m === 'object' && !Array.isArray(m))
        : [];
    if (!sessionId || !createdAtMs || !afterToolCallIds.length || !messages.length) {
        return null;
    }
    const sourceRequestId = typeof rec.sourceRequestId === 'string' && rec.sourceRequestId.trim().length
        ? rec.sourceRequestId.trim()
        : undefined;
    return {
        version: 1,
        sessionId,
        createdAtMs,
        afterToolCallIds,
        messages,
        ...(sourceRequestId ? { sourceRequestId } : {})
    };
}
export async function savePendingServerToolInjection(sessionId, pending) {
    const base = readSessionDirEnv();
    if (!base)
        return;
    const file = resolvePendingFile(base, sessionId);
    if (!file)
        return;
    await fs.mkdir(path.dirname(file), { recursive: true });
    const payload = {
        version: 1,
        sessionId,
        createdAtMs: pending.createdAtMs,
        afterToolCallIds: pending.afterToolCallIds,
        messages: pending.messages,
        ...(pending.sourceRequestId ? { sourceRequestId: pending.sourceRequestId } : {})
    };
    await writeJsonFileAtomic(file, payload);
}
export async function loadPendingServerToolInjection(sessionId) {
    const base = readSessionDirEnv();
    if (!base)
        return null;
    const file = resolvePendingFile(base, sessionId);
    if (!file)
        return null;
    try {
        const raw = await readJsonFile(file);
        return coercePending(raw);
    }
    catch {
        return null;
    }
}
export async function clearPendingServerToolInjection(sessionId) {
    const base = readSessionDirEnv();
    if (!base)
        return;
    const file = resolvePendingFile(base, sessionId);
    if (!file)
        return;
    try {
        await fs.rm(file, { force: true });
    }
    catch {
        // ignore
    }
}
