import { inferTaskPhaseKey } from "../phase-resolution.js";
function parseWorkspacePhaseKey(raw) {
    if (raw === null || raw === undefined) {
        return null;
    }
    const m = String(raw).trim().match(/^(\d+)/);
    return m ? m[1] : null;
}
function comparePhaseKeys(a, b) {
    const na = Number.parseInt(a, 10);
    const nb = Number.parseInt(b, 10);
    if (Number.isFinite(na) && Number.isFinite(nb) && String(na) === a && String(nb) === b) {
        return na - nb;
    }
    return a.localeCompare(b);
}
function phaseBucketLabel(key, current, next, count) {
    if (key === null) {
        return `Not Phased (${count})`;
    }
    if (key === current) {
        return `Phase ${key} (current) (${count})`;
    }
    if (key === next) {
        return `Phase ${key} (next) (${count})`;
    }
    if (current !== null) {
        const nk = Number.parseInt(key, 10);
        const nc = Number.parseInt(current, 10);
        if (Number.isFinite(nk) &&
            Number.isFinite(nc) &&
            String(nk) === key &&
            String(nc) === current &&
            nk > nc &&
            key !== next) {
            return `Phase ${key} (future) (${count})`;
        }
    }
    return `Phase ${key} (${count})`;
}
function emitBucketsFromMap(byKey, workspaceStatus, topPerBucket, mapTop, taskIdSelector) {
    const current = parseWorkspacePhaseKey(workspaceStatus?.currentKitPhase ?? null);
    const next = parseWorkspacePhaseKey(workspaceStatus?.nextKitPhase ?? null);
    const buckets = [];
    const emitted = new Set();
    const push = (key) => {
        const list = byKey.get(key) ?? [];
        const label = phaseBucketLabel(key, current, next, list.length);
        const row = {
            schemaVersion: 1,
            phaseKey: key,
            label,
            count: list.length,
            top: mapTop(list.slice(0, topPerBucket))
        };
        if (taskIdSelector) {
            row.taskIds = list.map(taskIdSelector);
        }
        buckets.push(row);
        if (key !== null) {
            emitted.add(key);
        }
    };
    /** Omit roadmap current/next slots when they have no tasks (avoids empty phase rows in the dashboard). */
    if (current !== null) {
        const curList = byKey.get(current) ?? [];
        if (curList.length > 0) {
            push(current);
        }
    }
    if (next !== null && next !== current) {
        const nextList = byKey.get(next) ?? [];
        if (nextList.length > 0) {
            push(next);
        }
    }
    const restKeys = [...byKey.keys()]
        .filter((k) => k !== null && !emitted.has(k))
        .sort(comparePhaseKeys);
    for (const k of restKeys) {
        push(k);
    }
    const unphased = byKey.get(null);
    if (unphased && unphased.length > 0) {
        push(null);
    }
    return buckets;
}
/**
 * Partition tasks into phase buckets (current / next from maintainer YAML, then other keys, then Not Phased).
 * `top` holds up to `topPerBucket` mapped rows per bucket for dashboard previews.
 */
export function buildDashboardPhaseBucketsForTasks(taskEntities, workspaceStatus, mapRow, topPerBucket, options) {
    const byKey = new Map();
    for (const t of taskEntities) {
        const k = inferTaskPhaseKey(t);
        const bucket = byKey.get(k);
        if (bucket) {
            bucket.push(t);
        }
        else {
            byKey.set(k, [t]);
        }
    }
    const idSel = options?.includeAllTaskIds ? (e) => e.id : undefined;
    return emitBucketsFromMap(byKey, workspaceStatus, topPerBucket, (items) => items.map(mapRow), idSel);
}
/**
 * Bucket blocking-analysis entries by the blocked task's phase (same ordering as task buckets).
 */
export function buildDashboardPhaseBucketsForBlocking(entries, resolveTask, workspaceStatus, topPerBucket) {
    const byKey = new Map();
    for (const e of entries) {
        const t = resolveTask(e.taskId);
        const k = inferTaskPhaseKey(t ? { phase: t.phase, phaseKey: t.phaseKey } : { phase: undefined, phaseKey: undefined });
        const row = { taskId: e.taskId, blockedBy: e.blockedBy };
        const bucket = byKey.get(k);
        if (bucket) {
            bucket.push(row);
        }
        else {
            byKey.set(k, [row]);
        }
    }
    return emitBucketsFromMap(byKey, workspaceStatus, topPerBucket, (items) => items);
}
