/**
 * Compute a sprint-level burndown from specs.
 * Uses createdAt to determine when work started and completedAt for done dates.
 * Returns daily data points sorted by date.
 * Returns empty array when no specs have dates.
 */
export function computeBurndown(specs) {
    if (specs.length === 0) {
        return [];
    }
    const datedSpecs = specs.filter((s) => Boolean(s.createdAt));
    if (datedSpecs.length === 0) {
        return [];
    }
    const startMs = Math.min(...datedSpecs.map((s) => toMs(s.createdAt)));
    const endMs = computeEndMs(datedSpecs, startMs);
    if (endMs <= startMs) {
        return [];
    }
    const total = specs.length;
    const spanDays = Math.round((endMs - startMs) / MS_PER_DAY);
    if (spanDays === 0) {
        return [];
    }
    // Build completion map: date string -> cumulative done count
    const doneByDate = new Map();
    for (const spec of specs) {
        if (spec.status === 'done' && spec.actuals?.completedAt) {
            const dateStr = toDateStr(spec.actuals.completedAt);
            if (dateStr) {
                doneByDate.set(dateStr, (doneByDate.get(dateStr) ?? 0) + 1);
            }
        }
    }
    const points = [];
    let cumulativeDone = 0;
    const stepDays = Math.max(1, Math.ceil(spanDays / 20)); // max 20 points
    for (let day = 0; day <= spanDays; day += stepDays) {
        const currentMs = startMs + day * MS_PER_DAY;
        const dateStr = toDateStr(new Date(currentMs).toISOString());
        if (!dateStr) {
            continue;
        }
        // Accumulate done specs up to current date
        for (const [dDate, cnt] of doneByDate) {
            if (dDate <= dateStr) {
                cumulativeDone += cnt;
                doneByDate.delete(dDate); // prevent double-counting
            }
        }
        const remaining = Math.max(0, total - cumulativeDone);
        const ideal = Math.round(total * (1 - day / spanDays));
        points.push({ date: dateStr, remaining, ideal });
    }
    return points;
}
const MS_PER_DAY = 86_400_000;
function toMs(dateStr) {
    const d = new Date(dateStr);
    return isNaN(d.getTime()) ? 0 : d.getTime();
}
function toDateStr(isoStr) {
    const d = new Date(isoStr);
    if (isNaN(d.getTime())) {
        return null;
    }
    return d.toISOString().slice(0, 10);
}
function computeEndMs(specs, startMs) {
    const completedSpecs = specs.filter((s) => Boolean(s.actuals?.completedAt));
    if (completedSpecs.length > 0) {
        return Math.max(...completedSpecs.map((s) => toMs(s.actuals?.completedAt ?? '')));
    }
    // Default: start + 4 weeks
    return startMs + 28 * MS_PER_DAY;
}
//# sourceMappingURL=burndown-aggregator.js.map