import { existsSync, mkdirSync } from 'node:fs';
import { appendFile, readdir, readFile, unlink } from 'node:fs/promises';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { jobRecordGuard } from '../../../../../modules/review-execution/entities/job/jobRecord.guard.js';
const DATE_FILENAME_PATTERN = /^(\d{4}-\d{2}-\d{2})\.jsonl$/;
function defaultRootDir() {
    return join(homedir(), '.claude-review', 'jobs');
}
function fileNameForCompletedAt(completedAt) {
    return `${completedAt.slice(0, 10)}.jsonl`;
}
function fileDateFromName(filename) {
    const match = filename.match(DATE_FILENAME_PATTERN);
    if (!match)
        return null;
    const parsed = new Date(`${match[1]}T00:00:00.000Z`);
    return Number.isNaN(parsed.getTime()) ? null : parsed;
}
function retentionThreshold(retentionDays, now) {
    const ms = retentionDays * 24 * 60 * 60 * 1000;
    return new Date(now.getTime() - ms);
}
export class JobHistoryFileSystemGateway {
    rootDir;
    logger;
    constructor(options) {
        this.rootDir = options.rootDir ?? defaultRootDir();
        this.logger = options.logger;
    }
    ensureRootDir() {
        if (!existsSync(this.rootDir)) {
            mkdirSync(this.rootDir, { recursive: true });
        }
    }
    async appendRecord(record) {
        this.ensureRootDir();
        const filePath = join(this.rootDir, fileNameForCompletedAt(record.completedAt));
        await appendFile(filePath, `${JSON.stringify(record)}\n`, 'utf-8');
    }
    async loadRecordsWithinWindow(retentionDays, now) {
        if (!existsSync(this.rootDir)) {
            return [];
        }
        const threshold = retentionThreshold(retentionDays, now);
        const entries = await readdir(this.rootDir);
        const collected = [];
        for (const entry of entries) {
            const fileDate = fileDateFromName(entry);
            if (!fileDate)
                continue;
            if (fileDate < threshold)
                continue;
            const records = await this.readFileRecords(join(this.rootDir, entry));
            collected.push(...records);
        }
        return collected;
    }
    async deleteRecordsOutsideWindow(retentionDays, now) {
        if (!existsSync(this.rootDir)) {
            return { deletedFilenames: [] };
        }
        const threshold = retentionThreshold(retentionDays, now);
        const entries = await readdir(this.rootDir);
        const deletedFilenames = [];
        for (const entry of entries) {
            const fileDate = fileDateFromName(entry);
            if (!fileDate)
                continue;
            if (fileDate >= threshold)
                continue;
            try {
                await unlink(join(this.rootDir, entry));
                deletedFilenames.push(entry);
            }
            catch {
                // Best-effort: a file we cannot delete is left in place silently.
            }
        }
        return { deletedFilenames };
    }
    async readFileRecords(filePath) {
        let raw;
        try {
            raw = await readFile(filePath, 'utf-8');
        }
        catch {
            return [];
        }
        const lines = raw.split('\n');
        const records = [];
        for (let index = 0; index < lines.length; index += 1) {
            const line = lines[index];
            if (line.trim().length === 0)
                continue;
            const parsedRecord = this.parseLine(line, index + 1);
            if (parsedRecord) {
                records.push(parsedRecord);
            }
        }
        return records;
    }
    parseLine(line, lineNumber) {
        let raw;
        try {
            raw = JSON.parse(line);
        }
        catch {
            this.logger.warn({ lineNumber }, `Ligne ${lineNumber} illisible, ignorée`);
            return null;
        }
        const result = jobRecordGuard.safeParse(raw);
        if (!result.success) {
            this.logger.warn({ lineNumber }, `Ligne ${lineNumber} illisible, ignorée`);
            return null;
        }
        return result.data;
    }
}
//# sourceMappingURL=jobHistory.fileSystem.gateway.js.map