/**
 * Discover SDK and Pi transcript files under a collected data transcripts directory.
 */
import fs from "node:fs";
import path from "node:path";
const UUID_PREFIX = /^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\./i;
function isImageArchiveFile(filename) {
    return /\.image-archive(\.\d{4}-\d{2}-\d{2})?\.jsonl$/.test(filename);
}
function isArchiveFile(filename) {
    return /\.archive(\.\d{4}-\d{2}-\d{2})?\.jsonl$/.test(filename);
}
function extractSessionIdFromFilename(filename) {
    const match = UUID_PREFIX.exec(filename);
    return match?.[1] ?? null;
}
function matchesSessionId(filename, sessionIds) {
    for (const id of sessionIds) {
        if (filename.startsWith(id))
            return true;
    }
    return false;
}
/**
 * Walk `transcriptDir` and group `.jsonl` transcript files by session UUID.
 * Includes flat Claude SDK files, `general/session.jsonl` layout, and
 * `pi-coding-agent/.../sessions/<uuid>.jsonl`.
 */
export function discoverTranscriptSessionFiles(transcriptDir, sessionIds) {
    const sessionIdSet = sessionIds ? new Set(sessionIds) : null;
    const bySession = new Map();
    const addFile = (sessionId, filePath, label, isArchive) => {
        if (!bySession.has(sessionId)) {
            bySession.set(sessionId, { label, archives: [], live: [] });
        }
        const bucket = bySession.get(sessionId);
        if (!bucket)
            return;
        if (isArchive)
            bucket.archives.push(filePath);
        else
            bucket.live.push(filePath);
    };
    // Legacy layout: subdirs with session.jsonl directly underneath
    const sessionDirs = [];
    for (const name of fs.readdirSync(transcriptDir).sort()) {
        const subdir = path.join(transcriptDir, name);
        if (fs.statSync(subdir).isDirectory() &&
            (fs.existsSync(path.join(subdir, "session.jsonl")) ||
                fs.existsSync(path.join(subdir, "session.archive.jsonl")))) {
            sessionDirs.push(subdir);
        }
    }
    if (sessionDirs.length === 0) {
        sessionDirs.push(transcriptDir);
    }
    for (const sdir of sessionDirs) {
        const sdirName = path.basename(sdir);
        const sessionArchive = path.join(sdir, "session.archive.jsonl");
        const sessionLive = path.join(sdir, "session.jsonl");
        if (fs.existsSync(sessionArchive) || fs.existsSync(sessionLive)) {
            const sid = sdirName;
            if (sessionIdSet && !sessionIdSet.has(sid))
                continue;
            if (fs.existsSync(sessionArchive)) {
                addFile(sid, sessionArchive, `${sdirName}/session.archive`, true);
            }
            if (fs.existsSync(sessionLive)) {
                addFile(sid, sessionLive, `${sdirName}/session`, false);
            }
            continue;
        }
        const allFiles = fs.readdirSync(sdir).sort();
        for (const f of allFiles) {
            if (isImageArchiveFile(f) || !f.endsWith(".jsonl"))
                continue;
            const sid = extractSessionIdFromFilename(f);
            if (!sid)
                continue;
            if (sessionIdSet && !matchesSessionId(f, sessionIdSet))
                continue;
            if (!bySession.has(sid)) {
                bySession.set(sid, { label: sdirName, archives: [], live: [] });
            }
        }
        for (const f of allFiles) {
            if (isImageArchiveFile(f) || !f.endsWith(".jsonl"))
                continue;
            const sid = extractSessionIdFromFilename(f);
            if (!sid || !bySession.has(sid))
                continue;
            const full = path.join(sdir, f);
            addFile(sid, full, `${sdirName}/${f}`, isArchiveFile(f));
        }
    }
    // Pi layout: pi-coding-agent/**/sessions/<uuid>.jsonl (avoid re-walking flat SDK files)
    const piRoot = path.join(transcriptDir, "pi-coding-agent");
    function walk(dir, rel) {
        let entries;
        try {
            entries = fs.readdirSync(dir, { withFileTypes: true });
        }
        catch {
            return;
        }
        for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
            const full = path.join(dir, entry.name);
            const relPath = rel ? `${rel}/${entry.name}` : entry.name;
            if (entry.isDirectory()) {
                walk(full, relPath);
                continue;
            }
            if (!entry.name.endsWith(".jsonl") || isImageArchiveFile(entry.name))
                continue;
            const sid = extractSessionIdFromFilename(entry.name);
            if (!sid)
                continue;
            if (sessionIdSet && !matchesSessionId(entry.name, sessionIdSet))
                continue;
            addFile(sid, full, relPath, isArchiveFile(entry.name));
        }
    }
    if (fs.existsSync(piRoot) && fs.statSync(piRoot).isDirectory()) {
        walk(piRoot, "pi-coding-agent");
    }
    const result = [];
    for (const [sessionId, { label, archives, live }] of bySession) {
        archives.sort();
        live.sort();
        const files = [...archives, ...live];
        if (files.length > 0) {
            result.push({ sessionId, label, files });
        }
    }
    result.sort((a, b) => a.sessionId.localeCompare(b.sessionId));
    return result;
}
/**
 * Collect session UUIDs from all discoverable transcript files.
 */
export function discoverSessionIdsFromTranscripts(transcriptDir) {
    const discovered = discoverTranscriptSessionFiles(transcriptDir);
    return discovered.map((d) => d.sessionId);
}
//# sourceMappingURL=transcript-discovery.js.map