/**
 * @fileoverview Pure, framework-agnostic helpers for the Permissions admin application's
 * AI-agent integration (Resource Access, User Access, Audit Log surfaces).
 *
 * These functions are intentionally free of Angular / component dependencies so they can be
 * unit-tested in isolation. Each Permissions resource component supplies a plain snapshot of
 * its 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 Permissions surfaces reveal WHO can access WHAT, the resources a user
 * can reach, and the history of permission changes. The agent-facing integration is strictly
 * READ-ONLY (lookup / filter / select / search). NOTHING here, and none of the client tools that
 * consume it, grants/revokes access, mutates a domain, impersonates a user, or edits an audit
 * record. Published context carries only display names, counts, active filter selections, and
 * BOUNDED samples of grantee / resource / entry names — never credentials, tokens, or secrets.
 */
/**
 * Upper bound on how many names / summaries each Permissions surface publishes in a bounded
 * list field. Keeping the streamed note bounded avoids flooding the co-agent with hundreds of
 * grantee or entry names; a companion `*Count` field reports the true total when truncated.
 */
export const PERMISSIONS_CONTEXT_LIST_CAP = 25;
/**
 * Cap a list of strings to {@link PERMISSIONS_CONTEXT_LIST_CAP} (or a caller-supplied cap).
 * Pure + deterministic; returns a new array and never mutates the input. Tolerates a
 * non-finite / negative cap by falling back to the default.
 */
export function capPermissionsList(values, cap = PERMISSIONS_CONTEXT_LIST_CAP) {
    const safeCap = Number.isFinite(cap) && cap >= 0 ? Math.floor(cap) : PERMISSIONS_CONTEXT_LIST_CAP;
    return values.slice(0, safeCap);
}
/**
 * Resolve an agent-supplied reference to a single candidate, the way a user names things:
 *   1. exact ID (case-insensitive)
 *   2. exact Name (case-insensitive, trimmed)
 *   3. first partial (contains) Name match (case-insensitive)
 *
 * Pure + deterministic over the supplied candidate list. Returns the matched candidate, or null
 * on a miss (callers turn the miss into a tolerant "available names" error). Never throws.
 *
 * @param input - whatever the agent passed (an ID or a display name)
 * @param candidates - the candidates available on this surface
 */
export function resolvePermissionsCandidate(input, candidates) {
    const needle = (input ?? '').trim().toLowerCase();
    if (!needle) {
        return null;
    }
    const byId = candidates.find((c) => c.ID.toLowerCase() === needle);
    if (byId) {
        return byId;
    }
    const byName = candidates.find((c) => c.Name.trim().toLowerCase() === needle);
    if (byName) {
        return byName;
    }
    return candidates.find((c) => c.Name.toLowerCase().includes(needle)) ?? null;
}
/**
 * Build a tolerant "not found" error message that lists a bounded sample of the available
 * candidate names so the agent can correct itself. Pure + deterministic.
 *
 * @param input - the unresolved reference the agent supplied
 * @param noun - what kind of thing wasn't found (e.g. "permission domain", "user")
 * @param candidates - the available candidates (a bounded sample of names is echoed back)
 */
export function buildPermissionsNotFoundError(input, noun, candidates) {
    const names = capPermissionsList(candidates.map((c) => c.Name), 10);
    const sample = names.length > 0 ? ` Available ${noun}s include: ${names.join(', ')}.` : '';
    return `No ${noun} matches "${input}".${sample}`;
}
/** Build the agent-visible context object for the Resource Access surface. */
export function buildResourceAccessAgentContext(input) {
    const context = {
        SelectedDomainName: input.SelectedDomainName,
        ResourceTypeInput: input.ResourceTypeInput || null,
        ResourceIdInput: input.ResourceIdInput || null,
        LastQueryLabel: input.LastQueryLabel,
        GranteeCount: input.GranteeCount,
        IsLoading: input.IsLoading,
        AvailableDomains: capPermissionsList(input.AvailableDomainNames),
    };
    if (input.AvailableDomainNames.length > PERMISSIONS_CONTEXT_LIST_CAP) {
        context['AvailableDomainCount'] = input.AvailableDomainNames.length;
    }
    if (input.ResourceTypes.length > 0) {
        context['ResourceTypes'] = capPermissionsList(input.ResourceTypes);
        if (input.ResourceTypes.length > PERMISSIONS_CONTEXT_LIST_CAP) {
            context['ResourceTypeCount'] = input.ResourceTypes.length;
        }
    }
    if (input.GranteeNames.length > 0) {
        context['GranteeNames'] = capPermissionsList(input.GranteeNames);
        if (input.GranteeNames.length > PERMISSIONS_CONTEXT_LIST_CAP) {
            // GranteeCount already reports the true total; this flag makes truncation explicit.
            context['GranteeNamesTruncated'] = true;
        }
    }
    return context;
}
/** Build the agent-visible context object for the User Access surface. */
export function buildUserAccessAgentContext(input) {
    const context = {
        SelectedUserId: input.SelectedUserId,
        SelectedUserName: input.SelectedUserName,
        DomainGroupCount: input.DomainSummaries.length,
        TotalAccessibleResourceCount: input.TotalResourceCount,
        IsLoadingPermissions: input.IsLoadingPermissions,
        AvailableUsers: capPermissionsList(input.AvailableUserNames),
    };
    if (input.AvailableUserCount > input.AvailableUserNames.length || input.AvailableUserNames.length > PERMISSIONS_CONTEXT_LIST_CAP) {
        context['AvailableUserCount'] = Math.max(input.AvailableUserCount, input.AvailableUserNames.length);
    }
    if (input.SelectedUserRoles.length > 0) {
        context['SelectedUserRoles'] = capPermissionsList(input.SelectedUserRoles);
        if (input.SelectedUserRoles.length > PERMISSIONS_CONTEXT_LIST_CAP) {
            context['SelectedUserRoleCount'] = input.SelectedUserRoles.length;
        }
    }
    if (input.DomainSummaries.length > 0) {
        context['AccessByDomain'] = input.DomainSummaries.slice(0, PERMISSIONS_CONTEXT_LIST_CAP).map((d) => ({
            DomainName: d.DomainName,
            ResourceCount: d.ResourceCount,
            Expanded: d.Expanded,
            ResourceNames: capPermissionsList(d.ResourceNames),
            ResourceNamesTruncated: d.ResourceNames.length > PERMISSIONS_CONTEXT_LIST_CAP,
        }));
        const expanded = input.DomainSummaries.filter((d) => d.Expanded).map((d) => d.DomainName);
        context['ExpandedDomains'] = capPermissionsList(expanded);
    }
    return context;
}
/** Build the agent-visible context object for the Audit Log surface. */
export function buildAuditLogAgentContext(input) {
    const context = {
        DomainFilter: input.DomainFilter || null,
        UserFilter: input.UserFilter || null,
        UserFilterName: input.UserFilterName,
        StartDate: input.StartDate || null,
        EndDate: input.EndDate || null,
        EntryCount: input.EntryCount,
        IsLoading: input.IsLoading,
        HasRunQuery: input.HasRunQuery,
        HasActiveFilters: Boolean(input.DomainFilter || input.UserFilter || input.StartDate || input.EndDate),
        AvailableDomains: capPermissionsList(input.AvailableDomainNames),
        AvailableUsers: capPermissionsList(input.AvailableUserNames),
    };
    if (input.AvailableDomainNames.length > PERMISSIONS_CONTEXT_LIST_CAP) {
        context['AvailableDomainCount'] = input.AvailableDomainNames.length;
    }
    if (input.AvailableUserCount > input.AvailableUserNames.length || input.AvailableUserNames.length > PERMISSIONS_CONTEXT_LIST_CAP) {
        context['AvailableUserCount'] = Math.max(input.AvailableUserCount, input.AvailableUserNames.length);
    }
    if (input.RecentEntries.length > 0) {
        context['RecentEntries'] = input.RecentEntries.slice(0, PERMISSIONS_CONTEXT_LIST_CAP);
        if (input.EntryCount > PERMISSIONS_CONTEXT_LIST_CAP) {
            context['RecentEntriesTruncated'] = true;
        }
    }
    return context;
}
//# sourceMappingURL=permissions-agent-context.js.map