/**
 * index-md.mjs — .aperant/tasks/INDEX.md regenerator (C29).
 */
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
import { loadMergedProjectConfig } from '../config/load.mjs';
import { withFileLock } from '../util/fs-lock.mjs';
import { formatDateDisplay, formatTimeDisplay } from './format.mjs';
/**
 * Regenerate .aperant/tasks/INDEX.md from state.json.
 * One line per task — lightweight project task management view.
 */
export function regenerateTaskIndex(targetDir) {
    const statePath = join(targetDir, '.aperant', 'state.json');
    if (!existsSync(statePath))
        return;
    // AUDIT-001: read through the merged loader so per-device
    // preferences.date_format / preferences.time_format overrides land
    // even when the shared config.json no longer carries those fields.
    // Guard: malformed config.local.json must not crash every task state
    // transition — fall back to shared-config-only read and warn on stderr.
    let config;
    try {
        config = loadMergedProjectConfig(targetDir) ?? {};
    }
    catch (e) {
        process.stderr.write(`[index-md] config.local.json parse error — using shared config only: ${e.message}\n`);
        config = {};
    }
    if (config.preferences?.task_index === false)
        return;
    const state = JSON.parse(readFileSync(statePath, 'utf-8'));
    const timeFormat = config.preferences?.time_format || '24h';
    const active = state.active_tasks ? Object.values(state.active_tasks) : [];
    const completed = (state.completed_tasks || []).slice().reverse();
    // C28 — group rows by scope. Scope order: the default `project` scope
    // first, everything else alphabetical. Within each scope: active rows
    // first (by creation time desc), then completed rows (most recent first).
    const scopeSet = new Set();
    for (const t of active)
        scopeSet.add(t?.scope || 'project');
    for (const t of completed)
        scopeSet.add(t?.scope || 'project');
    const scopeOrder = (a, b) => {
        if (a === b)
            return 0;
        if (a === 'project')
            return -1;
        if (b === 'project')
            return 1;
        return a.localeCompare(b);
    };
    const scopes = Array.from(scopeSet).sort(scopeOrder);
    if (scopes.length === 0)
        scopes.push('project');
    const lines = ['# Task Index', ''];
    const totalCount = active.length + completed.length;
    if (totalCount === 0) {
        lines.push('| Status | Date | Time | Task | ID |');
        lines.push('|--------|------|------|------|----|');
        lines.push('| | | | *No tasks yet* | |');
    }
    else {
        for (const scope of scopes) {
            const scopeActive = active.filter((t) => (t?.scope || 'project') === scope);
            const scopeCompleted = completed.filter((t) => (t?.scope || 'project') === scope);
            if (scopeActive.length === 0 && scopeCompleted.length === 0)
                continue;
            lines.push(`## Scope: ${scope}`);
            lines.push('');
            lines.push('| Status | Date | Time | Task | ID |');
            lines.push('|--------|------|------|------|----|');
            for (const t of scopeActive) {
                const d = new Date(t.created_at);
                const date = formatDateDisplay(d, config.preferences?.date_format);
                const time = formatTimeDisplay(d, timeFormat);
                lines.push(`| \u25b6 active | ${date} | ${time} | ${t.description} | \`${t.id}\` |`);
            }
            for (const t of scopeCompleted) {
                const d = new Date(t.completed_at);
                const date = formatDateDisplay(d, config.preferences?.date_format);
                const time = formatTimeDisplay(d, timeFormat);
                const verdict = t.qa_verdict ? ` (${t.qa_verdict})` : '';
                lines.push(`| \u2713 done${verdict} | ${date} | ${time} | ${t.description} | \`${t.id}\` |`);
            }
            lines.push('');
        }
    }
    lines.push('', `*Auto-generated by apt-tools \u2014 ${new Date().toISOString()}*`, '');
    const indexPath = join(targetDir, '.aperant', 'tasks', 'INDEX.md');
    mkdirSync(join(targetDir, '.aperant', 'tasks'), { recursive: true });
    // Lock-protected — C28 R4. Concurrent regenerators must not interleave.
    withFileLock(indexPath, () => {
        writeFileSync(indexPath, lines.join('\n'), 'utf-8');
    }, { projectRoot: targetDir });
}
//# sourceMappingURL=index-md.mjs.map