/**
 * @fileoverview Pure, framework-agnostic helpers for the Knowledge Hub
 * **Scheduling** resource component's AI-agent integration.
 *
 * Free of Angular / component dependencies so they can be unit-tested in
 * isolation. The component supplies plain snapshots of its job + run state and
 * these helpers shape the deep agent context + resolve agent-supplied job
 * references (by id → name → contains).
 *
 * 🔒 SAFETY: these helpers only PROJECT state and RESOLVE references — no
 * mutation, no side effects.
 */
import { boundNameList, AGENT_CONTEXT_NAME_LIST_CAP } from '../../../shared/agent-tool-validation';
/** The status values a scheduled job can hold (the FilterSchedulesByStatus tool's domain). */
export const VALID_SCHEDULE_STATUSES = ['Active', 'Paused', 'Disabled'];
/**
 * Resolve a job reference the way the agent expresses it — by id (exact,
 * case-insensitive) → name (exact, case-insensitive) → name *contains*
 * (case-insensitive). Pure + deterministic.
 *
 * @returns the matched job, or null on a miss.
 */
export function resolveScheduledJob(input, jobs) {
    const needle = input.trim().toLowerCase();
    if (!needle)
        return null;
    const byID = jobs.find(j => j.ID.toLowerCase() === needle);
    if (byID)
        return byID;
    const byName = jobs.find(j => j.Name.toLowerCase() === needle);
    if (byName)
        return byName;
    return jobs.find(j => j.Name.toLowerCase().includes(needle)) ?? null;
}
/** Build a tolerant "no schedule matches" error listing a bounded sample of names. */
export function buildScheduleNotFoundError(input, available) {
    const sample = boundNameList(available, 10).join(', ');
    const more = available.length > 10 ? ` (+${available.length - 10} more)` : '';
    return `No scheduled job matches "${input}". Available jobs: ${sample}${more}.`;
}
/** Count jobs in a particular status (case-sensitive on the stored value). */
function countByStatus(jobs, status) {
    return jobs.filter(j => j.Status === status).length;
}
/**
 * Find the name of the job that is due next, scanning `NextRunAt` for the
 * smallest future-or-now timestamp. Returns null when no job has a NextRunAt.
 * Pure + deterministic.
 */
export function nextDueJobName(jobs) {
    let best = null;
    let bestTime = Infinity;
    for (const j of jobs) {
        if (!j.NextRunAt)
            continue;
        const t = new Date(j.NextRunAt).getTime();
        if (Number.isFinite(t) && t < bestTime) {
            bestTime = t;
            best = j;
        }
    }
    return best?.Name ?? null;
}
/**
 * Build the agent-visible context for the Scheduling surface. Publishes deep
 * counts (by lifecycle status), the active status filter + search, the next-due
 * job, and a **bounded** structured list of the filtered jobs (name · status ·
 * cron · success rate) so the agent can pick one to edit/open. A companion
 * truncation flag tells it when the list is capped.
 */
export function buildSchedulingAgentContext(input) {
    const all = input.AllJobs;
    const filtered = input.FilteredJobs;
    const ctx = {
        IsLoading: input.IsLoading,
        TotalJobs: all.length,
        VisibleJobs: filtered.length,
        ActiveCount: countByStatus(all, 'Active'),
        PausedCount: countByStatus(all, 'Paused'),
        DisabledCount: countByStatus(all, 'Disabled'),
        StatusFilter: input.StatusFilter || 'All',
        SearchQuery: input.SearchQuery,
        RecentRunCount: input.RecentRunCount,
        NextDueJobName: nextDueJobName(all),
        VisibleJobNames: boundNameList(filtered.map(j => j.Name)),
        Jobs: filtered.slice(0, AGENT_CONTEXT_NAME_LIST_CAP).map(j => ({
            Name: j.Name,
            Status: j.Status,
            Cron: j.CronExpression ?? null,
            SuccessRate: j.RunCount && j.RunCount > 0
                ? Math.round(((j.SuccessCount ?? 0) / j.RunCount) * 100)
                : null,
        })),
    };
    if (filtered.length > AGENT_CONTEXT_NAME_LIST_CAP) {
        ctx['JobsTruncated'] = true;
    }
    return ctx;
}
//# sourceMappingURL=scheduling-agent-context.js.map