/**
 * Index caching for O(1) label/phase/hierarchy lookups.
 * Ported from lib/data/cache.sh
 *
 * @epic T4454
 * @task T4530
 */
/**
 * In-memory cache for task indices with checksum-based staleness detection.
 */
export class TaskCache {
    labelIndex = new Map();
    phaseIndex = new Map();
    parentIndex = new Map();
    childrenIndex = new Map();
    depthIndex = new Map();
    checksum = '';
    initialized = false;
    /**
     * Compute a checksum from task data for staleness detection.
     */
    computeChecksum(tasks) {
        return tasks
            .map((t) => `${t.id}:${t.status}:${t.parentId ?? ''}:${t.phase ?? ''}:${(t.labels ?? []).join(',')}`)
            .sort()
            .join('|');
    }
    /**
     * Initialize or rebuild cache from tasks.
     * Returns true if cache was rebuilt, false if already valid.
     */
    init(tasks) {
        const newChecksum = this.computeChecksum(tasks);
        if (this.initialized && newChecksum === this.checksum) {
            return false;
        }
        this.buildLabelIndex(tasks);
        this.buildPhaseIndex(tasks);
        this.buildHierarchyIndex(tasks);
        this.checksum = newChecksum;
        this.initialized = true;
        return true;
    }
    buildLabelIndex(tasks) {
        this.labelIndex.clear();
        for (const task of tasks) {
            if (!task.labels?.length)
                continue;
            for (const label of task.labels) {
                const existing = this.labelIndex.get(label) ?? [];
                existing.push(task.id);
                this.labelIndex.set(label, existing);
            }
        }
    }
    buildPhaseIndex(tasks) {
        this.phaseIndex.clear();
        for (const task of tasks) {
            if (!task.phase)
                continue;
            const existing = this.phaseIndex.get(task.phase) ?? [];
            existing.push(task.id);
            this.phaseIndex.set(task.phase, existing);
        }
    }
    buildHierarchyIndex(tasks) {
        this.parentIndex.clear();
        this.childrenIndex.clear();
        this.depthIndex.clear();
        const taskMap = new Map(tasks.map((t) => [t.id, t]));
        for (const task of tasks) {
            this.parentIndex.set(task.id, task.parentId ?? null);
            if (task.parentId) {
                const siblings = this.childrenIndex.get(task.parentId) ?? [];
                siblings.push(task.id);
                this.childrenIndex.set(task.parentId, siblings);
            }
        }
        // Compute depths
        for (const task of tasks) {
            let depth = 0;
            let current = task;
            const visited = new Set();
            while (current.parentId && !visited.has(current.parentId)) {
                visited.add(current.parentId);
                const parent = taskMap.get(current.parentId);
                if (!parent)
                    break;
                depth++;
                current = parent;
            }
            this.depthIndex.set(task.id, depth);
        }
    }
    /** Get task IDs by label. */
    getTasksByLabel(label) {
        return this.labelIndex.get(label) ?? [];
    }
    /** Get task IDs by phase. */
    getTasksByPhase(phase) {
        return this.phaseIndex.get(phase) ?? [];
    }
    /** Get all labels. */
    getAllLabels() {
        return [...this.labelIndex.keys()];
    }
    /** Get all phases. */
    getAllPhases() {
        return [...this.phaseIndex.keys()];
    }
    /** Get label count for a specific label. */
    getLabelCount(label) {
        return this.getTasksByLabel(label).length;
    }
    /** Get parent ID for a task. */
    getParent(taskId) {
        return this.parentIndex.get(taskId) ?? null;
    }
    /** Get children IDs for a task. */
    getChildren(taskId) {
        return this.childrenIndex.get(taskId) ?? [];
    }
    /** Get depth for a task. */
    getDepth(taskId) {
        return this.depthIndex.get(taskId) ?? 0;
    }
    /** Get child count. */
    getChildCount(taskId) {
        return this.getChildren(taskId).length;
    }
    /** Get root tasks (no parent). */
    getRootTasks() {
        return [...this.parentIndex.entries()]
            .filter(([, parent]) => parent === null)
            .map(([id]) => id);
    }
    /** Get leaf tasks (no children). */
    getLeafTasks() {
        const parentSet = new Set(this.childrenIndex.keys());
        return [...this.parentIndex.keys()].filter((id) => !parentSet.has(id) || this.getChildCount(id) === 0);
    }
    /** Force invalidation and rebuild. */
    invalidate() {
        this.labelIndex.clear();
        this.phaseIndex.clear();
        this.parentIndex.clear();
        this.childrenIndex.clear();
        this.depthIndex.clear();
        this.checksum = '';
        this.initialized = false;
    }
    /** Get cache statistics. */
    getStats() {
        let maxDepth = 0;
        for (const d of this.depthIndex.values()) {
            if (d > maxDepth)
                maxDepth = d;
        }
        return {
            initialized: this.initialized,
            labelCount: this.labelIndex.size,
            phaseCount: this.phaseIndex.size,
            taskCount: this.parentIndex.size,
            maxDepth,
        };
    }
}
//# sourceMappingURL=cache.js.map