/**
 * @fileoverview Knowledge Hub Configuration Resource Component
 *
 * Full configuration dashboard for Knowledge Hub infrastructure:
 * Vector DB provider management, vector index CRUD, embedding model selection,
 * pipeline settings, full-text index config, and scoring thresholds.
 */
import { OnDestroy, AfterViewInit } from '@angular/core';
import { Subject } from 'rxjs';
import { ResourceData, MJSearchScopeEntity } from '@memberjunction/core-entities';
import { BaseResourceComponent, NavigationService } from '@memberjunction/ng-shared';
import { MJLeftNavItem, MJLeftNavSection } from '@memberjunction/ng-ui-components';
import { SearchScopeChildGridColumn } from '@memberjunction/ng-search';
import * as i0 from "@angular/core";
/** Configuration section definition */
interface ConfigSection {
    ID: string;
    Label: string;
    Icon: string;
    Description: string;
}
/** Pipeline configuration settings */
interface PipelineConfig {
    AutotagOnIngest: boolean;
    VectorizeOnIngest: boolean;
    DefaultBatchSize: number;
    MaxConcurrentJobs: number;
}
/** Threshold settings */
interface ThresholdConfig {
    DuplicateAbsolute: number;
    DuplicatePotential: number;
    SearchRelevance: number;
    AutotagConfidence: number;
}
/** Vector DB provider display record */
interface VectorDBRecord {
    ID: string;
    Name: string;
    ClassKey: string;
    Description: string;
    CredentialID: string | null;
    CredentialName: string | null;
}
/** Vector index display record */
interface VectorIndexRecord {
    ID: string;
    Name: string;
    EmbeddingModel: string;
    EmbeddingModelID: string;
    VectorDatabase: string;
    VectorDatabaseID: string;
}
/** Embedding model display record */
interface EmbeddingModelRecord {
    ID: string;
    Name: string;
}
/** Full-text searchable entity */
interface FTSEntityRecord {
    EntityName: string;
    IndexedFields: string[];
    TitleField: string;
    SnippetField: string;
    Enabled: boolean;
}
export declare class KnowledgeConfigResourceComponent extends BaseResourceComponent implements AfterViewInit, OnDestroy {
    private cdr;
    protected navigationService: NavigationService;
    protected destroy$: Subject<void>;
    GetResourceDisplayName(_data: ResourceData): Promise<string>;
    GetResourceIconClass(_data: ResourceData): Promise<string>;
    Sections: ConfigSection[];
    ActiveSection: string;
    IsLoading: boolean;
    IsSaving: boolean;
    HasUnsavedChanges: boolean;
    PipelineSettings: PipelineConfig;
    ThresholdSettings: ThresholdConfig;
    VectorDBProviders: VectorDBRecord[];
    get HasVectorDBProvider(): boolean;
    VectorIndexes: VectorIndexRecord[];
    get HasVectorIndex(): boolean;
    EmbeddingModels: EmbeddingModelRecord[];
    get HasEmbeddingModel(): boolean;
    get EmbeddingModelName(): string;
    AvailableCredentials: {
        ID: string;
        Name: string;
    }[];
    IsSavingCredential: boolean;
    private entityDocuments;
    get SetupStepsCompleted(): number;
    get VectorSetupComplete(): boolean;
    FTSEntities: FTSEntityRecord[];
    IsLoadingFTSEntities: boolean;
    FTSFilterText: string;
    get EnabledFTSCount(): number;
    get FilteredFTSEntities(): FTSEntityRecord[];
    ShowCreateIndexForm: boolean;
    IsCreatingIndex: boolean;
    NewIndexName: string;
    NewIndexVectorDBID: string;
    NewIndexEmbeddingModelID: string;
    /** All SearchScope rows the current user can manage. */
    SearchScopes: MJSearchScopeEntity[];
    /** Currently-selected scope ID — drives child-grid loading. */
    ActiveScopeID: string | null;
    IsLoadingScopes: boolean;
    /** Which sub-tab of the selected scope is open. */
    ActiveScopeTab: 'definition' | 'providers' | 'indexes' | 'entities' | 'storage' | 'permissions';
    /** Column spec for the Providers child grid. */
    readonly ScopeProviderColumns: SearchScopeChildGridColumn[];
    /** Column spec for the External Indexes child grid. */
    readonly ScopeExternalIndexColumns: SearchScopeChildGridColumn[];
    /** Column spec for the Entities child grid. */
    readonly ScopeEntityColumns: SearchScopeChildGridColumn[];
    /** Column spec for the Storage Accounts child grid. */
    readonly ScopeStorageColumns: SearchScopeChildGridColumn[];
    /**
     * Column spec for the SearchScopePermission child grid (Phase 2A).
     * Editable surface — admins author per-user / per-role grants here.
     * Each row binds either a User or a Role (XOR enforced by the DB CHECK
     * constraint, surfaced as a save-time error for now). Resolution order
     * lives in SearchScopePermissionResolver.
     */
    readonly ScopePermissionColumns: SearchScopeChildGridColumn[];
    ngAfterViewInit(): void;
    /**
     * 🔒 SAFETY BOUNDARY (Config surface)
     * ----------------------------------
     * EXPOSED to the agent: navigation (switch section / tab), idempotent reloads
     * (ReloadConfiguration, LoadSearchAnalytics, LoadPermissionsAudit), read-only
     * filters (FTS filter, permissions-audit filters), selection (select scope),
     * and opening a search scope's record/full-form for VIEWING.
     *
     * NEVER EXPOSED (destructive / credential-bearing — deliberate UI actions
     * only): SaveConfiguration / persist thresholds, CreateIndex / DeleteIndex,
     * CreateNewScope / SaveActiveScope / DeleteActiveScope, and
     * SaveProviderCredential (changes credentials). These mutate infrastructure
     * or write credentials and stay user-driven. The agent may *navigate to* and
     * *open* these surfaces, never commit them.
     */
    /**
     * Publish the current Config surface state to the AI agent. Re-emitted on
     * every section change / scope load so the streamed context never goes stale.
     * Deep context is shaped by the pure {@link buildKnowledgeConfigAgentContext}.
     */
    private emitAgentContext;
    /**
     * Register the SAFE, agent-actionable operations for the Config surface.
     * Navigation, idempotent reloads, read-only filters, selection, and
     * view-only record opens. All resolve references tolerantly (id → name →
     * contains) and never throw. See the SAFETY BOUNDARY above.
     */
    private registerAgentTools;
    ngOnDestroy(): void;
    /** Wraps `Sections` for `<mj-left-nav>`. Single unlabeled section. */
    get navSections(): MJLeftNavSection[];
    /**
     * Active section metadata — drives the `<mj-page-header-interior>` Title +
     * Subtitle for the current section. Reusing the existing Sections array
     * (already used to drive the left rail) keeps section identity DRY.
     */
    get currentSection(): ConfigSection | undefined;
    /** Adapter for `<mj-left-nav>`'s `(ItemClicked)` output. */
    onNavItemClicked(item: MJLeftNavItem): void;
    SelectSection(sectionId: string): void;
    AnalyticsLoaded: boolean;
    AnalyticsLoading: boolean;
    AnalyticsTotalRuns: number;
    AnalyticsSuccessRate: number;
    AnalyticsAvgLatencyMs: number;
    AnalyticsP95LatencyMs: number;
    AnalyticsTotalRerankerCostCents: number;
    AnalyticsHitRate: number;
    AnalyticsTopScopes: Array<{
        ScopeID: string;
        Name: string;
        Count: number;
        AvgLatencyMs: number;
    }>;
    AnalyticsTopFailures: Array<{
        Reason: string;
        Count: number;
    }>;
    AnalyticsRerankerSpend: Array<{
        Reranker: string;
        Count: number;
        TotalCents: number;
    }>;
    LoadSearchAnalytics(): Promise<void>;
    /** Fetch the raw SearchExecutionLog rows. Returns null on RunView failure (already logged). */
    private fetchSearchExecutionRows;
    /** Total runs, success rate, hit rate, avg + p95 latency, total reranker spend. */
    private computeAnalyticsKpis;
    /**
     * Per-scope volume rollup → top 10 by Count. Fetches scope names from
     * `this.SearchScopes` when already loaded, otherwise loads them on demand
     * so the unscoped audit-only path still gets human-readable labels.
     */
    private computeAnalyticsTopScopes;
    /** Top 5 failure reasons across non-Success rows. */
    private computeAnalyticsTopFailures;
    /** Per-reranker spend rollup, sorted descending by total cost. */
    private computeAnalyticsRerankerSpend;
    PermissionsLoaded: boolean;
    PermissionsLoading: boolean;
    PermissionsRows: Array<{
        ID: string;
        SearchScopeID: string;
        SearchScopeName: string;
        UserID: string | null;
        UserName: string | null;
        UserEmail: string | null;
        RoleID: string | null;
        RoleName: string | null;
        PermissionLevel: string;
    }>;
    PermissionsFilterScope: string;
    PermissionsFilterPrincipal: string;
    PermissionsFilterLevel: string;
    LoadPermissionsAudit(): Promise<void>;
    get FilteredPermissionsRows(): typeof this.PermissionsRows;
    RefreshPermissionsAudit(): void;
    /**
     * Pull permissions, scopes, users, roles in one batched call.
     * `BypassCache: true` on every view — this is an audit dashboard, so we
     * want SQL-truth even when permission/scope rows have been written
     * outside the normal `BaseEntity.Save()` path (test harnesses,
     * direct-SQL maintenance, recovery scripts). Without this, scope names
     * can render as "(unknown)" if the cache was populated before the
     * underlying row was inserted.
     *
     * Returns null on RunView failure (already logged).
     */
    private fetchPermissionsAuditData;
    /**
     * Shape the raw fetched data into the audit-table rows. Drops
     * permission rows whose SearchScope is not visible to the current user
     * (MJ's row-level filtering hides scopes from non-Owner callers).
     * Surfacing the permission row with "(unknown)" leaks the row's
     * existence without giving the auditor anything useful — the underlying
     * API already enforces visibility, so this is a UX call, not a security
     * one.
     */
    private shapePermissionsAuditRows;
    LoadSearchScopes(): Promise<void>;
    SelectScope(scopeID: string): void;
    SelectScopeTab(tab: 'definition' | 'providers' | 'indexes' | 'entities' | 'storage' | 'permissions'): void;
    get ActiveScope(): MJSearchScopeEntity | null;
    CreateNewScope(): Promise<void>;
    /**
     * Pick a placeholder Name that doesn't collide with an existing scope.
     * `__mj.SearchScope.Name` is UNIQUE, so reusing the literal string
     * "New Search Scope" twice in a row throws SQL Server's UQ violation.
     * Walk an incrementing suffix until we find one the in-memory list
     * doesn't already use ("New Search Scope", "New Search Scope 2",
     * "New Search Scope 3", ...). Existing scopes table is small and
     * already loaded, so the linear scan is trivially cheap.
     */
    private pickUniqueNewScopeName;
    /**
     * Open the active scope in its full custom form (a new MJExplorer tab).
     * The dashboard view exposes a quick-edit subset; the full form has the
     * Phase 2D / Phase 4 surfaces (Fusion Weights sliders, Reranker dropdown,
     * Reranker Budget Cents, Live Preview, Search Scope Test Queries panel,
     * Search Execution Logs panel, etc.). No-ops for the built-in Global
     * scope (no detail to author) and any scope without an ID yet.
     */
    OpenActiveScopeFullForm(): void;
    SaveActiveScope(): Promise<void>;
    /** Format a scope Date field as the string expected by <input type="datetime-local">. */
    FormatScopeDate(value: Date | string | null | undefined): string;
    /** Write a datetime-local input value back to the scope entity. Empty clears to null. */
    SetScopeDate(scope: MJSearchScopeEntity, field: 'StartAt' | 'EndAt', value: string): void;
    DeleteActiveScope(): Promise<void>;
    OnSettingChanged(): void;
    SaveConfiguration(): Promise<void>;
    ResetConfiguration(): void;
    /** Handle toggling an FTS entity */
    OnFTSEntityToggled(entity: FTSEntityRecord): void;
    FormatThreshold(value: number): string;
    /** Open the create index inline form */
    OpenCreateIndexForm(): void;
    /** Cancel creating an index */
    CancelCreateIndex(): void;
    /** Create a new vector index */
    CreateIndex(): Promise<void>;
    /** Delete a vector index */
    DeleteIndex(indexId: string): Promise<void>;
    /** Update the credential linked to a vector database provider */
    SaveProviderCredential(provider: VectorDBRecord): Promise<void>;
    private loadConfiguration;
    private loadFTSEntities;
    private loadVectorDBProvidersFromEngine;
    private loadVectorIndexesFromEngine;
    /** Load entity documents and seed threshold settings from the first document's values */
    private loadEntityDocumentsAndThresholds;
    /** Persist threshold settings back to all active entity documents */
    private persistThresholdsToEntityDocuments;
    private loadEmbeddingModels;
    static ɵfac: i0.ɵɵFactoryDeclaration<KnowledgeConfigResourceComponent, never>;
    static ɵcmp: i0.ɵɵComponentDeclaration<KnowledgeConfigResourceComponent, "app-knowledge-config-resource", never, {}, {}, never, never, false, never>;
}
/** Tree-shaking prevention */
export declare function LoadKnowledgeConfigResource(): void;
export {};
//# sourceMappingURL=knowledge-config-resource.component.d.ts.map