import { createReadStream } from 'fs';
import { statSync } from 'fs';
import { createInterface } from 'readline';
import { cleanUserText, filterAssistantJsonlParts, isAssistantReflectionText, isMeaningfulAssistantText, isNoiseChatText, parseUserImagePaths, stripJsonlRedactionArtifacts, } from './message-filter.js';
import { canonicalizeImagePaths } from './media-path.js';
function classifyJsonlLine(line, lineNo) {
    if (!line.trim()) {
        return {
            lineNo,
            role: '—',
            textPreview: '',
            textLen: 0,
            tools: [],
            inLenta: false,
            skipReason: 'blank',
        };
    }
    try {
        const row = JSON.parse(line);
        const role = row.role ?? '?';
        const tools = [];
        const parts = [];
        const rawParts = [];
        for (const c of row.message?.content ?? []) {
            if (c.type === 'tool_use' && c.name)
                tools.push(String(c.name));
            if (c.type === 'text' && c.text) {
                rawParts.push(c.text);
                const t = cleanUserText(c.text);
                if (t)
                    parts.push(t);
            }
        }
        const rawJoined = rawParts.join('\n').trim();
        const preview = rawJoined.slice(0, 600);
        if (role === 'user') {
            const images = canonicalizeImagePaths(parseUserImagePaths(rawJoined));
            const text = stripJsonlRedactionArtifacts(cleanUserText(parts.join('\n').trim()));
            const hasImages = images.length > 0;
            if ((!text || isNoiseChatText(text)) && !hasImages) {
                return {
                    lineNo,
                    role,
                    textPreview: preview || '(noise)',
                    textLen: rawJoined.length,
                    tools,
                    inLenta: false,
                    skipReason: 'user-noise',
                };
            }
            return {
                lineNo,
                role,
                textPreview: text || (hasImages ? '[images]' : preview),
                textLen: rawJoined.length,
                tools,
                inLenta: true,
            };
        }
        if (role === 'assistant') {
            if (!parts.length && tools.length) {
                return {
                    lineNo,
                    role,
                    textPreview: preview || '[REDACTED]',
                    textLen: rawJoined.length,
                    tools,
                    inLenta: false,
                    skipReason: 'tool-only',
                };
            }
            const filtered = filterAssistantJsonlParts(parts);
            const text = filtered.join('\n').trim();
            if (!text) {
                let skipReason = 'empty-parts';
                for (const p of parts) {
                    if (isAssistantReflectionText(p))
                        skipReason = 'reflection';
                    else if (isNoiseChatText(p))
                        skipReason = 'noise';
                    else if (!isMeaningfulAssistantText(p))
                        skipReason = 'not-meaningful';
                }
                return {
                    lineNo,
                    role,
                    textPreview: preview || '[REDACTED]',
                    textLen: rawJoined.length,
                    tools,
                    inLenta: false,
                    skipReason,
                };
            }
            return {
                lineNo,
                role,
                textPreview: text.slice(0, 600),
                textLen: rawJoined.length,
                tools,
                inLenta: true,
            };
        }
        return {
            lineNo,
            role,
            textPreview: preview,
            textLen: rawJoined.length,
            tools,
            inLenta: false,
            skipReason: 'unknown-role',
        };
    }
    catch {
        return {
            lineNo,
            role: '?',
            textPreview: line.slice(0, 120),
            textLen: line.length,
            tools: [],
            inLenta: false,
            skipReason: 'json-error',
        };
    }
}
/** Read JSONL file rows for debug live view (`afterLine` exclusive, or tail when afterLine=0). */
export async function readJsonlLiveSnapshot(filePath, agentId, opts) {
    const afterLine = Math.max(0, opts?.afterLine ?? 0);
    const tail = Math.min(500, Math.max(0, opts?.tail ?? 0));
    const maxNew = Math.min(128, Math.max(1, opts?.maxNew ?? 64));
    let fileSize = 0;
    let totalLines = 0;
    try {
        fileSize = statSync(filePath).size;
    }
    catch {
        return {
            agentId,
            filePath: null,
            fileSize: 0,
            totalLines: 0,
            updatedAt: Date.now(),
            rows: [],
        };
    }
    const buffered = [];
    const rows = [];
    const rl = createInterface({ input: createReadStream(filePath), crlfDelay: Infinity });
    for await (const line of rl) {
        totalLines++;
        if (afterLine > 0) {
            if (totalLines <= afterLine)
                continue;
            rows.push(classifyJsonlLine(line, totalLines));
            continue;
        }
        buffered.push(classifyJsonlLine(line, totalLines));
    }
    if (afterLine === 0) {
        if (tail > 0)
            rows.push(...buffered.slice(-tail));
        else
            rows.push(...buffered.slice(-maxNew));
    }
    else if (rows.length > maxNew) {
        rows.splice(0, rows.length - maxNew);
    }
    return {
        agentId,
        filePath,
        fileSize,
        totalLines,
        updatedAt: Date.now(),
        rows,
    };
}
