// Copyright (c) 2026 Hellmai Ltd
// SPDX-License-Identifier: AGPL-3.0-only
/**
 * Session Cross-Link Index (WU-2755, extracted from WU-2754 delegation-list.ts)
 *
 * Shared helper for cross-linking delegation registry records (WU-2753) with
 * per-WU session records (WU-2754). Extracted so both `delegation:list` and
 * `mem:context --include-roster` can compose the coordination roster without
 * duplicating the lookup logic.
 *
 * Kernel-agnostic: every field is an opaque string. The pack-layer vocabulary
 * (lifecycle_role, specialty_profile) is defined by the software-delivery
 * pack; the CLI merely transports strings and rejects malformed shapes.
 */
import { existsSync, readFileSync, readdirSync } from 'node:fs';
import path from 'node:path';
import { LUMENFLOW_PATHS } from '@lumenflow/core/wu-constants';
const SESSION_COMPAT_POINTER_FILE = 'current.json';
/**
 * Read all `<WU>.json` session records under `.lumenflow/sessions/` and
 * return them indexed by wu_id. The `current.json` compatibility pointer is
 * skipped because it mirrors a per-WU record.
 *
 * Cross-linkage is best-effort — missing directory, parse errors, or v1
 * legacy shape must not throw; callers still render their primary view even
 * when the sessions directory is empty.
 */
export function collectSessionCrossLinkIndex(baseDir) {
    const records = collectActiveSessionRecords(baseDir);
    const sessionsPath = path.join(baseDir, LUMENFLOW_PATHS.SESSIONS);
    const index = new Map();
    if (!existsSync(sessionsPath)) {
        return index;
    }
    for (const record of records) {
        index.set(record.wu_id, record);
    }
    return index;
}
export function collectActiveSessionRecords(baseDir) {
    const sessionsPath = path.join(baseDir, LUMENFLOW_PATHS.SESSIONS);
    if (!existsSync(sessionsPath)) {
        return [];
    }
    let entries;
    try {
        entries = readdirSync(sessionsPath);
    }
    catch {
        return [];
    }
    const records = [];
    for (const entry of entries) {
        if (!entry.endsWith('.json') || entry === SESSION_COMPAT_POINTER_FILE) {
            continue;
        }
        try {
            const raw = readFileSync(path.join(sessionsPath, entry), { encoding: 'utf-8' });
            const parsed = JSON.parse(raw);
            if (typeof parsed.wu_id !== 'string' ||
                parsed.wu_id.length === 0 ||
                typeof parsed.completed === 'string') {
                continue;
            }
            const record = { wu_id: parsed.wu_id };
            if (typeof parsed.session_id === 'string' && parsed.session_id.length > 0) {
                record.session_id = parsed.session_id;
            }
            if (typeof parsed.display_name === 'string' && parsed.display_name.length > 0) {
                record.display_name = parsed.display_name;
            }
            if (typeof parsed.lane === 'string' && parsed.lane.length > 0) {
                record.lane = parsed.lane;
            }
            if (typeof parsed.started === 'string' && parsed.started.length > 0) {
                record.started = parsed.started;
            }
            if (typeof parsed.last_heartbeat === 'string' && parsed.last_heartbeat.length > 0) {
                record.last_heartbeat = parsed.last_heartbeat;
            }
            else if (typeof parsed.started === 'string' && parsed.started.length > 0) {
                record.last_heartbeat = parsed.started;
            }
            if (typeof parsed.lifecycle_role === 'string' && parsed.lifecycle_role.length > 0) {
                record.lifecycle_role = parsed.lifecycle_role;
            }
            if (typeof parsed.specialty_profile === 'string' && parsed.specialty_profile.length > 0) {
                record.specialty_profile = parsed.specialty_profile;
            }
            if (typeof parsed.delegation_id === 'string' && parsed.delegation_id.length > 0) {
                record.delegation_id = parsed.delegation_id;
            }
            records.push(record);
        }
        catch {
            continue;
        }
    }
    return records.sort((left, right) => left.wu_id.localeCompare(right.wu_id));
}
export function resolveActiveSessionTarget(baseDir, target) {
    const normalizedTarget = target.trim();
    if (normalizedTarget.length === 0) {
        return null;
    }
    const sessions = collectActiveSessionRecords(baseDir);
    for (const session of sessions) {
        if (session.session_id === normalizedTarget) {
            return {
                sessionId: normalizedTarget,
                ...(session.display_name ? { displayName: session.display_name } : {}),
            };
        }
    }
    for (const session of sessions) {
        if (session.display_name === normalizedTarget && session.session_id) {
            return {
                sessionId: session.session_id,
                displayName: normalizedTarget,
            };
        }
    }
    return null;
}
/**
 * Find the session record that links to a given delegation. Prefers an
 * explicit `delegation_id` reference; falls back to matching `wu_id` against
 * the delegation target so sessions written before WU-2754 still cross-link
 * on the weaker association.
 */
export function resolveSessionForDelegation(delegation, sessionIndex) {
    for (const record of sessionIndex.values()) {
        if (record.delegation_id && record.delegation_id === delegation.id) {
            return record;
        }
    }
    return sessionIndex.get(delegation.targetWuId);
}
//# sourceMappingURL=session-cross-link.js.map