import fs from 'fs/promises';
import path from 'path';
import { resolveNexusStateDir } from '../../engines/runtime-registry.js';
function isSafeStateKey(stateKey) {
    return typeof stateKey === 'string' && /^[a-zA-Z0-9_-]+$/.test(stateKey);
}
function workspaceRunsDir(stateKey) {
    return path.join(resolveNexusStateDir(), 'workspaces', stateKey, 'runs');
}
export function runTimestamp(run) {
    const candidates = [
        run?.updatedAt,
        run?.completedAt,
        run?.createdAt,
        run?.startedAt,
        run?.timestamp,
        run?.queuedAt,
    ];
    for (const candidate of candidates) {
        if (candidate == null)
            continue;
        const value = typeof candidate === 'number' ? candidate : Date.parse(String(candidate));
        if (Number.isFinite(value) && value > 0)
            return value;
    }
    return 0;
}
function normalizeArtifactRun(run, runDir, fallbackTs) {
    const runId = String(run?.runId ?? run?.id ?? path.basename(runDir) ?? '').trim();
    if (!runId)
        return null;
    const ts = runTimestamp(run) || fallbackTs;
    return {
        ...run,
        id: run.id ?? runId,
        runId,
        artifactsPath: typeof run.artifactsPath === 'string' && run.artifactsPath.trim()
            ? run.artifactsPath
            : runDir,
        createdAt: run.createdAt ?? run.startedAt ?? ts,
        updatedAt: run.updatedAt ?? run.completedAt ?? ts,
        source: run.source ?? 'workspace-artifact',
    };
}
export async function readWorkspaceArtifactRun(stateKey, runId) {
    if (!isSafeStateKey(stateKey) || !runId)
        return undefined;
    const runDir = path.join(workspaceRunsDir(stateKey), runId);
    const runPath = path.join(runDir, 'run.json');
    try {
        const [raw, stat] = await Promise.all([
            fs.readFile(runPath, 'utf8'),
            fs.stat(runPath),
        ]);
        return normalizeArtifactRun(JSON.parse(raw), runDir, stat.mtimeMs) ?? undefined;
    }
    catch {
        return undefined;
    }
}
export async function listWorkspaceArtifactRuns(stateKey, limit) {
    if (!isSafeStateKey(stateKey))
        return [];
    const runsDir = workspaceRunsDir(stateKey);
    const max = Math.max(1, limit);
    try {
        const entries = await fs.readdir(runsDir, { withFileTypes: true });
        const candidateEntries = entries
            .filter((entry) => entry.isDirectory())
            .sort((left, right) => right.name.localeCompare(left.name))
            .slice(0, Math.max(32, max * 4));
        const candidates = await Promise.all(candidateEntries.map(async (entry) => {
            const runDir = path.join(runsDir, entry.name);
            const runPath = path.join(runDir, 'run.json');
            try {
                const stat = await fs.stat(runPath);
                return { entry, mtimeMs: stat.mtimeMs };
            }
            catch {
                return null;
            }
        }));
        const selected = candidates
            .filter((candidate) => Boolean(candidate))
            .sort((left, right) => right.mtimeMs - left.mtimeMs)
            .slice(0, max);
        const runs = await Promise.all(selected
            .map(async ({ entry, mtimeMs }) => {
            const runDir = path.join(runsDir, entry.name);
            const runPath = path.join(runDir, 'run.json');
            try {
                const raw = await fs.readFile(runPath, 'utf8');
                return normalizeArtifactRun(JSON.parse(raw), runDir, mtimeMs);
            }
            catch {
                return null;
            }
        }));
        return runs
            .filter((run) => Boolean(run))
            .sort((left, right) => runTimestamp(right) - runTimestamp(left))
            .slice(0, max);
    }
    catch {
        return [];
    }
}
