import { appendFile, mkdir, open, readFile, rm } from 'node:fs/promises';
import { dirname, join, resolve } from 'node:path';
import { MemorySchemas } from './schemas.js';
/**
 * Owns memory maintenance JSONL files and lock-file persistence.
 */
export class MemoryMaintenanceRepository {
    memoryRoot;
    constructor(memoryRoot) {
        this.memoryRoot = memoryRoot;
    }
    async readPendingCandidates() {
        const entries = await this.readCandidateLogEntries();
        const processed = new Set();
        const pending = [];
        for (const entry of entries) {
            if ('kind' in entry) {
                processed.add(entry.candidateId);
                continue;
            }
            pending.push(entry);
        }
        return pending.filter((candidate) => !processed.has(candidate.id));
    }
    async appendCandidate(candidate) {
        await this.appendJsonLine(this.candidatesPath(), candidate);
    }
    async appendCandidateStatusEvents(candidateIds, runId, now) {
        const recordedAt = now().toISOString();
        const records = candidateIds.map((candidateId) => ({
            kind: 'candidate_status',
            candidateId,
            status: 'processed',
            runId,
            recordedAt,
        }));
        await this.appendJsonLines(this.candidatesPath(), records);
    }
    async appendMaintenanceRun(run) {
        await this.appendJsonLine(this.runsPath(), run);
    }
    async readRecentMaintenanceRuns(limit = 5) {
        const lines = await this.readJsonlLines(this.runsPath());
        return lines
            .map((line) => this.parseMaintenanceRun(line))
            .filter((run) => Boolean(run))
            .slice(-limit)
            .reverse();
    }
    async writeLock(lockPath, record) {
        await mkdir(dirname(lockPath), { recursive: true });
        const handle = await open(lockPath, 'wx');
        try {
            await handle.writeFile(`${JSON.stringify(record)}\n`, 'utf8');
        }
        finally {
            await handle.close();
        }
    }
    async readLock(lockPath) {
        try {
            const parsed = JSON.parse(await readFile(lockPath, 'utf8'));
            const result = MemorySchemas.parseMaintenanceLock(parsed);
            return result.success ? result.data : undefined;
        }
        catch (error) {
            if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
                return undefined;
            }
            return undefined;
        }
    }
    async removeLock(lockPath) {
        await rm(lockPath, { force: true });
    }
    maintenanceLockPath() {
        return join(this.resolveRoot(), '_maintenance', 'maintenance.lock');
    }
    async readCandidateLogEntries() {
        const lines = await this.readJsonlLines(this.candidatesPath());
        return lines
            .map((line) => this.parseCandidateLogEntry(line))
            .filter((entry) => Boolean(entry));
    }
    candidatesPath() {
        return join(this.resolveRoot(), '_maintenance', 'candidates.jsonl');
    }
    runsPath() {
        return join(this.resolveRoot(), '_maintenance', 'runs.jsonl');
    }
    async appendJsonLine(path, record) {
        await this.appendJsonLines(path, [record]);
    }
    async appendJsonLines(path, records) {
        await mkdir(dirname(path), { recursive: true });
        await appendFile(path, `${records.map((record) => JSON.stringify(record)).join('\n')}\n`, 'utf8');
    }
    async readJsonlLines(path) {
        try {
            const raw = await readFile(path, 'utf8');
            return raw.split(/\r?\n/u).filter((line) => line.trim());
        }
        catch (error) {
            if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
                return [];
            }
            throw error;
        }
    }
    parseCandidateLogEntry(line) {
        try {
            const parsed = JSON.parse(line);
            const result = MemorySchemas.parseCandidateLogEntry(parsed);
            return result.success ? result.data : undefined;
        }
        catch {
            return undefined;
        }
    }
    parseMaintenanceRun(line) {
        try {
            const parsed = JSON.parse(line);
            const result = MemorySchemas.parseMaintenanceRun(parsed);
            return result.success ? result.data : undefined;
        }
        catch {
            return undefined;
        }
    }
    resolveRoot() {
        return resolve(this.memoryRoot);
    }
}
//# sourceMappingURL=maintenance-repository.js.map