/**
 * @fileoverview Pure helpers for the Archiving app's AI-agent integration.
 *
 * These functions are intentionally free of Angular / component dependencies so
 * they can be unit-tested in isolation. The two Archiving resource components
 * supply a plain snapshot of their current state and these helpers shape it into
 * the key-value `AgentContext` object that flows to the async chat agent and the
 * realtime co-agent via `NavigationService.SetAgentContext`.
 *
 * 🔒 SAFETY BOUNDARY: the Archiving surfaces are wired READ-ONLY. These helpers
 * only describe and bucket state — they perform no archiving, purging, policy
 * mutation, or run execution. See the SAFETY BOUNDARY comments in the resource
 * components for the full list of intentionally-excluded operations.
 */
/**
 * Upper bound on how many names (policy names, entity names, recent-run names)
 * any Archiving surface publishes in a name-list context field. Keeping the
 * streamed note bounded avoids flooding the co-agent with hundreds of names;
 * surfaces publish a companion total-count field when the list is truncated.
 */
export const ARCHIVE_NAME_LIST_CAP = 25;
/**
 * Cap an array of names to {@link ARCHIVE_NAME_LIST_CAP} entries. Pure +
 * deterministic so the published context shape stays unit-testable. Never throws;
 * never mutates the input.
 *
 * @param names - the full list (caller owns de-duplication / ordering)
 * @returns the first N names, where N is the cap
 */
export function capArchiveNames(names) {
    return names.slice(0, ARCHIVE_NAME_LIST_CAP);
}
/**
 * The set of run-status filter values the Run History surface accepts. `'all'`
 * means no status filter is applied (the default). The remaining values mirror
 * the typed `MJ: Archive Runs.Status` union (Cancelled | Complete | Failed |
 * PartialSuccess | Running).
 */
export const ARCHIVE_RUN_STATUS_FILTERS = [
    'all',
    'Complete',
    'PartialSuccess',
    'Failed',
    'Running',
    'Cancelled',
];
/**
 * Type-guard / validator for a run-status filter string. Keeps the
 * `FilterArchiveRunsByStatus` client tool tolerant of arbitrary agent input —
 * only the known status values (plus `'all'`) are accepted.
 *
 * @param status - candidate status string (may be anything the agent passes)
 * @returns true when `status` is one of {@link ARCHIVE_RUN_STATUS_FILTERS}
 */
export function isValidArchiveRunStatusFilter(status) {
    return typeof status === 'string' && ARCHIVE_RUN_STATUS_FILTERS.includes(status);
}
/**
 * Resolve an agent-supplied run reference (an ID or a configuration name) to one
 * of the loaded runs. Matches the way an agent names things, in order:
 *   1. exact ID (case-insensitive)
 *   2. exact configuration name (case-insensitive)
 *   3. first configuration-name *contains* match (case-insensitive)
 *
 * Pure + deterministic over the supplied run list, so it's unit-testable in
 * isolation. Returns a tolerant error listing the available run names on a miss.
 *
 * @param reference - whatever the agent passed (a run ID or a configuration name)
 * @param runs - the runs currently loaded in the viewer
 * @returns the matched run, or a clear error message
 */
export function resolveArchiveRun(reference, runs) {
    const needle = reference.trim().toLowerCase();
    if (!needle) {
        return { ok: false, error: 'A run ID or configuration name is required.' };
    }
    if (runs.length === 0) {
        return { ok: false, error: 'No archive runs are currently loaded to select from.' };
    }
    const byId = runs.find((r) => r.ID.toLowerCase() === needle);
    if (byId) {
        return { ok: true, run: byId };
    }
    const byName = runs.find((r) => (r.ConfigurationName ?? '').toLowerCase() === needle);
    if (byName) {
        return { ok: true, run: byName };
    }
    const byContains = runs.find((r) => (r.ConfigurationName ?? '').toLowerCase().includes(needle));
    if (byContains) {
        return { ok: true, run: byContains };
    }
    const sample = capArchiveNames(runs.map((r) => r.ConfigurationName).filter((n) => !!n)).join(', ');
    return {
        ok: false,
        error: `No archive run matches "${reference}". Available runs include: ${sample}.`,
    };
}
/**
 * Bucket a list of runs into Total / Successful / Failed / Running counts.
 *
 * `Complete` and `PartialSuccess` both count as successful (the run produced
 * output even if some records were skipped/failed within it). Comparison is
 * case-insensitive so the helper is tolerant of casing drift from the data layer.
 *
 * @param runs - the runs to bucket (only their Status is read)
 * @returns the four outcome counts
 */
export function computeArchiveRunStatusCounts(runs) {
    let successful = 0;
    let failed = 0;
    let running = 0;
    for (const run of runs) {
        const status = (run.Status ?? '').toLowerCase();
        if (status === 'complete' || status === 'partialsuccess') {
            successful++;
        }
        else if (status === 'failed') {
            failed++;
        }
        else if (status === 'running') {
            running++;
        }
    }
    return {
        TotalRuns: runs.length,
        SuccessfulRuns: successful,
        FailedRuns: failed,
        RunningRuns: running,
    };
}
/**
 * Filter a list of runs by a status filter. `'all'` returns the runs unchanged;
 * any other value keeps only runs whose status matches (case-insensitive).
 *
 * @param runs - the runs to filter
 * @param filter - the active status filter
 * @returns the filtered subset (a new array)
 */
export function filterArchiveRunsByStatus(runs, filter) {
    if (filter === 'all') {
        return [...runs];
    }
    const wanted = filter.toLowerCase();
    return runs.filter((r) => (r.Status ?? '').toLowerCase() === wanted);
}
/**
 * Build the agent-visible context for the Archive Configuration surface.
 *
 * 🔒 Read-only: describes policy/entity counts + bounded policy/entity names and
 * load state only. The agent cannot create, edit, or delete policies through this
 * context.
 *
 * Note: `ScheduledJobCount` / `NextScheduledRun` are intentionally absent — the
 * archive schema has no scheduling concept (no Schedule/Cron/NextRun fields on
 * `MJ: Archive Configurations`), so there is no honest data source for them.
 *
 * @param input - the component's current state snapshot
 * @returns a flat key-value object suitable for `SetAgentContext`
 */
export function buildArchiveConfigAgentContext(input) {
    const context = {
        Surface: 'ArchiveConfiguration',
        PolicyCount: input.PolicyCount,
        ActivePolicyCount: input.ActivePolicyCount,
        EntitiesUnderArchive: input.EntitiesUnderArchive,
        IsLoading: input.IsLoading,
    };
    if (input.PolicyNames.length > 0) {
        context['PolicyNames'] = capArchiveNames(input.PolicyNames);
        if (input.PolicyNames.length > ARCHIVE_NAME_LIST_CAP) {
            context['PolicyNameCount'] = input.PolicyNames.length;
        }
    }
    if (input.ArchivedEntityNames.length > 0) {
        context['ArchivedEntityNames'] = capArchiveNames(input.ArchivedEntityNames);
        if (input.ArchivedEntityNames.length > ARCHIVE_NAME_LIST_CAP) {
            context['ArchivedEntityNameCount'] = input.ArchivedEntityNames.length;
        }
    }
    return context;
}
/**
 * Build the agent-visible context for the Archive Run History surface.
 *
 * 🔒 Read-only: describes run outcome counts (by status), the active filter, a
 * bounded list of recent runs (id · name · status), and which run (if any) is
 * open for inspection. The agent cannot run, cancel, retry, or purge anything
 * through this context.
 *
 * Note: a per-run `DryRun` flag is intentionally absent — `MJ: Archive Runs` has
 * no dry-run column (the dry-run concept lives in the Record-Set-Processing
 * substrate, not archiving), so there is no honest data source for it.
 *
 * @param input - the component's current state snapshot
 * @returns a flat key-value object suitable for `SetAgentContext`
 */
export function buildArchiveRunsAgentContext(input) {
    const context = {
        Surface: 'ArchiveRunHistory',
        TotalRuns: input.Counts.TotalRuns,
        SuccessfulRuns: input.Counts.SuccessfulRuns,
        FailedRuns: input.Counts.FailedRuns,
        RunningRuns: input.Counts.RunningRuns,
        StatusFilter: input.StatusFilter,
        FilteredRunCount: input.FilteredRunCount,
        SelectedRunId: input.SelectedRunId,
        SelectedRunName: input.SelectedRunName,
        SelectedRunStatus: input.SelectedRunStatus,
        IsLoading: input.IsLoading,
    };
    if (input.RecentRuns.length > 0) {
        context['RecentRuns'] = input.RecentRuns.slice(0, ARCHIVE_NAME_LIST_CAP);
        if (input.RecentRuns.length > ARCHIVE_NAME_LIST_CAP) {
            context['RecentRunCount'] = input.RecentRuns.length;
        }
    }
    return context;
}
//# sourceMappingURL=archive-agent-context.js.map