export const MAX_JOURNAL_ENTRIES = 90;
export const LAST_SESSION_THRESHOLD_HOURS = 24;
// ---------------------------------------------------------------------------
// Archive helpers
// ---------------------------------------------------------------------------
/** Prune entries to the most recent `maxEntries`. */
export function archiveEntries(entries, maxEntries) {
    if (entries.length <= maxEntries) {
        return entries;
    }
    return entries.slice(-maxEntries);
}
// ---------------------------------------------------------------------------
// Event helpers
// ---------------------------------------------------------------------------
/** Create a journal event with the current timestamp. */
export function createJournalEvent(type, opts = {}) {
    return { type, timestamp: new Date().toISOString(), ...opts };
}
/** Apply an event to the matching open session, or start a new one. */
export function applyEventToSessions(entries, sessionId, event) {
    const updated = [...entries];
    const openIdx = updated.findIndex((e) => e.sessionId === sessionId && !e.endedAt);
    if (openIdx === -1) {
        // Start new session entry
        const newEntry = {
            sessionId,
            startedAt: event.timestamp,
            specsWorked: event.specId ? [event.specId] : [],
            criteriaCompleted: event.type === 'criterion-completed' ? 1 : 0,
            filesModified: [],
            commits: event.commitHash ? [event.commitHash] : [],
            events: [event],
        };
        return [...updated, newEntry];
    }
    const sessionRef = updated[openIdx];
    /* v8 ignore start — noUncheckedIndexedAccess guard, openIdx is always valid here */
    if (!sessionRef) {
        return updated;
    }
    /* v8 ignore stop */
    const session = { ...sessionRef };
    session.events = [...session.events, event];
    if (event.specId && !session.specsWorked.includes(event.specId)) {
        session.specsWorked = [...session.specsWorked, event.specId];
    }
    if (event.type === 'criterion-completed') {
        session.criteriaCompleted = session.criteriaCompleted + 1;
    }
    if (event.commitHash && !session.commits.includes(event.commitHash)) {
        session.commits = [...session.commits, event.commitHash];
    }
    updated[openIdx] = session;
    return updated;
}
// ---------------------------------------------------------------------------
// Summary formatting
// ---------------------------------------------------------------------------
/** Format the last session entry into a compact summary string. */
export function formatLastSessionSummary(entry) {
    const date = new Date(entry.startedAt).toLocaleDateString();
    const specs = entry.specsWorked.join(', ') || 'sin specs';
    const lastCommit = entry.commits[entry.commits.length - 1];
    const commitPart = lastCommit ? `, último commit: ${lastCommit}` : '';
    return `Última sesión [${date}]: trabajaste en ${specs}, completaste ${entry.criteriaCompleted} criterios${commitPart}`;
}
/** Check if a session is older than the given threshold in hours. */
export function isOlderThan(entry, thresholdHours) {
    const hoursSince = (Date.now() - new Date(entry.startedAt).getTime()) / (1000 * 60 * 60);
    return hoursSince > thresholdHours;
}
// ---------------------------------------------------------------------------
// Session Brief builder
// ---------------------------------------------------------------------------
/** Build a compact SessionBrief from project specs + journal state. */
export function buildBrief(input) {
    const { specs, journal, tokenBudget, experienceLevel = 'expert' } = input;
    const specMap = new Map(specs.map((s) => [s.id, s]));
    // Classify specs
    const inProgress = specs.filter((s) => s.status === 'implementing').map((s) => s.id);
    const pendingUnblocked = specs
        .filter((s) => {
        if (s.status !== 'approved' && s.status !== 'draft') {
            return false;
        }
        return s.dependencies.every((depId) => {
            const dep = specMap.get(depId);
            return dep?.status === 'done';
        });
    })
        .sort((a, b) => {
        const order = { critical: 0, high: 1, medium: 2, low: 3 };
        const rA = order[a.risk] ?? 2;
        const rB = order[b.risk] ?? 2;
        return rA - rB;
    })
        .map((s) => s.id);
    const blockers = specs
        .filter((s) => {
        if (s.status !== 'approved' && s.status !== 'draft') {
            return false;
        }
        return s.dependencies.some((depId) => {
            const dep = specMap.get(depId);
            return dep && dep.status !== 'done';
        });
    })
        .map((s) => s.id);
    // Build 1-3 suggestions from top unblocked specs
    const suggestions = pendingUnblocked.slice(0, 3).map((id) => {
        const spec = specMap.get(id);
        const depsOk = spec?.dependencies.every((d) => specMap.get(d)?.status === 'done') ?? true;
        const hours = spec?.estimation.devHours;
        const reason = depsOk ? `dependencias completas, ~${hours ?? '?'}h estimado` : 'disponible';
        return { spec: id, reason };
    });
    // Last session summary from journal
    const lastEntry = journal.entries[journal.entries.length - 1];
    let lastSessionSummary;
    if (lastEntry) {
        const summary = formatLastSessionSummary(lastEntry);
        if (isOlderThan(lastEntry, LAST_SESSION_THRESHOLD_HOURS)) {
            lastSessionSummary = `[>24h] ${summary}`;
        }
        else {
            lastSessionSummary = summary;
        }
    }
    const brief = {
        inProgress,
        pendingUnblocked,
        blockers,
        suggestions,
        lastSessionSummary,
    };
    if (typeof tokenBudget === 'number') {
        brief.tokenBudget = tokenBudget;
    }
    // Beginner mode: add narrative hint in suggestions
    if (experienceLevel === 'beginner' && suggestions.length > 0) {
        const first = suggestions[0];
        if (first) {
            suggestions[0] = {
                spec: first.spec,
                reason: `Recomendado para empezar: ${first.reason}`,
            };
        }
    }
    return brief;
}
//# sourceMappingURL=session-journal.js.map