import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { createRandomId } from "@best-agent/foundation";
import { readJsonLines } from "./json-lines.js";
export class LocalResearchStore {
    #threads;
    constructor(threads) {
        this.#threads = threads;
    }
    async createRun(input) {
        const run = {
            createdAt: new Date().toISOString(),
            objective: input.objective,
            runId: createRandomId("research"),
            status: "running",
            subquestionCount: input.subquestionCount,
            threadId: input.threadId,
            turnId: input.turnId,
        };
        this.#ensureRunDirectory(input.threadId, run.runId);
        this.#appendRun(input.threadId, run);
        writeJsonFile(this.#subquestionsPath(input.threadId, run.runId), []);
        return run;
    }
    async updateRun(threadId, run) {
        this.#ensureRunDirectory(threadId, run.runId);
        this.#appendRun(threadId, run);
    }
    async writeSubquestions(threadId, runId, subquestions) {
        this.#ensureRunDirectory(threadId, runId);
        writeJsonFile(this.#subquestionsPath(threadId, runId), subquestions);
    }
    async appendEvidence(threadId, runId, evidence) {
        this.#ensureRunDirectory(threadId, runId);
        appendFileSync(this.#evidencePath(threadId, runId), `${JSON.stringify(evidence)}\n`);
    }
    async writeReport(threadId, runId, report) {
        this.#ensureRunDirectory(threadId, runId);
        writeJsonFile(this.#reportPath(threadId, runId), report);
    }
    async getRun(threadId, runId) {
        const runs = this.#readRuns(threadId);
        return runs.get(runId) ?? null;
    }
    async getLatestRun(threadId) {
        const runs = Array.from(this.#readRuns(threadId).values()).sort((left, right) => {
            const leftTime = left.completedAt ?? left.createdAt;
            const rightTime = right.completedAt ?? right.createdAt;
            return rightTime.localeCompare(leftTime);
        });
        return runs[0] ?? null;
    }
    async getReport(threadId, runId) {
        return readJsonFile(this.#reportPath(threadId, runId));
    }
    async getLatestReport(threadId) {
        const run = await this.getLatestRun(threadId);
        if (!run) {
            return { report: null, run: null };
        }
        return {
            report: await this.getReport(threadId, run.runId),
            run,
        };
    }
    async listEvidence(threadId, runId) {
        const run = runId ? await this.getRun(threadId, runId) : await this.getLatestRun(threadId);
        if (!run) {
            return { evidence: [], run: null };
        }
        return {
            evidence: readJsonLines(this.#evidencePath(threadId, run.runId)),
            run,
        };
    }
    #researchDir(threadId) {
        return join(this.#threads.getThreadPaths(threadId).threadDir, "research");
    }
    #runsPath(threadId) {
        return join(this.#researchDir(threadId), "runs.jsonl");
    }
    #runDir(threadId, runId) {
        return join(this.#researchDir(threadId), runId);
    }
    #subquestionsPath(threadId, runId) {
        return join(this.#runDir(threadId, runId), "subquestions.json");
    }
    #evidencePath(threadId, runId) {
        return join(this.#runDir(threadId, runId), "evidence.jsonl");
    }
    #reportPath(threadId, runId) {
        return join(this.#runDir(threadId, runId), "report.json");
    }
    #ensureRunDirectory(threadId, runId) {
        mkdirSync(this.#runDir(threadId, runId), { recursive: true });
    }
    #appendRun(threadId, run) {
        mkdirSync(this.#researchDir(threadId), { recursive: true });
        appendFileSync(this.#runsPath(threadId), `${JSON.stringify(run)}\n`);
    }
    #readRuns(threadId) {
        const runs = new Map();
        for (const run of readJsonLines(this.#runsPath(threadId))) {
            runs.set(run.runId, run);
        }
        return runs;
    }
}
function readJsonFile(path) {
    if (!existsSync(path)) {
        return null;
    }
    return JSON.parse(readFileSync(path, "utf8"));
}
function writeJsonFile(path, value) {
    writeFileSync(path, JSON.stringify(value, null, 2));
}
//# sourceMappingURL=research-store.js.map