import { apiFetch, apiPath, type ApiSettings } from "@govoplan/core-webui"; export type SearchExternalReference = { system: string; object_type: string; object_id: string; maturity: string; connector_id?: string | null; canonical_url?: string | null; }; export type SearchResult = { provider_id: string; module_id: string; resource_type: string; resource_id: string; title: string; summary?: string | null; url: string; score: number; highlights: string[]; breadcrumbs: string[]; external_reference?: SearchExternalReference | null; metadata: Record; source_revision?: string | null; provenance: Record; }; export type SearchResponse = { query: string; results: SearchResult[]; diagnostics: Array<{ provider_id: string; status: "unavailable"; message: string; }>; next_cursor?: string | null; has_more: boolean; }; export type SearchProvider = { id: string; module_id: string; resource_types: string[]; order: number; }; export type SearchResourceType = { provider_id: string; module_id: string; resource_type: string; label: string; order: number; }; export type SearchProviderListResponse = { providers: SearchProvider[]; resources: SearchResourceType[]; }; export type SearchIndexState = { provider_id: string; module_id: string; resource_type: string; index_version: number; status: string; checkpoint_cursor?: string | null; high_watermark?: string | null; last_change_cursor?: string | null; indexed_documents: number; rejected_documents: number; rebuild_started_at?: string | null; rebuild_completed_at?: string | null; last_success_at?: string | null; last_error?: string | null; }; export type SearchDiagnostics = { backend: string; trigram_available: boolean; queue: Record; queue_oldest_age_seconds?: number | null; states: SearchIndexState[]; }; export type SearchChangeDispatch = { selected: number; applied: number; retrying: number; quarantined: number; }; export type SearchModuleReconcile = { disabled_documents: number; enabled_documents: number; }; export type SearchRequest = { query: string; modules?: string[]; resourceTypes?: string[]; contextKind?: "global" | "module" | "resource"; contextId?: string; limit?: number; offset?: number; cursor?: string; language?: string; }; export function search( settings: ApiSettings, request: SearchRequest, signal?: AbortSignal ): Promise { return apiFetch( settings, apiPath("/api/v1/search", { q: request.query, module: request.modules, resource_type: request.resourceTypes, context_kind: request.contextKind, context_id: request.contextId, limit: request.limit, offset: request.offset, cursor: request.cursor, language: request.language }), { signal } ); } export function listSearchProviders( settings: ApiSettings, signal?: AbortSignal ): Promise { return apiFetch( settings, "/api/v1/search/providers", { signal } ); } export function getSearchDiagnostics( settings: ApiSettings, signal?: AbortSignal ): Promise { return apiFetch( settings, "/api/v1/search/admin/diagnostics", { signal } ); } export function reconcileSearchModules( settings: ApiSettings ): Promise { return apiFetch( settings, "/api/v1/search/admin/reconcile-modules", { method: "POST" } ); } export function processSearchChanges( settings: ApiSettings, limit = 100 ): Promise { return apiFetch( settings, apiPath("/api/v1/search/admin/changes/process", { limit }), { method: "POST" } ); } export function startSearchRebuild( settings: ApiSettings, providerId: string, resourceType: string ): Promise<{ state: SearchIndexState }> { return apiFetch<{ state: SearchIndexState }>( settings, `/api/v1/search/admin/rebuilds/${encodeURIComponent(providerId)}/${encodeURIComponent(resourceType)}/start`, { method: "POST" } ); } export function continueSearchRebuild( settings: ApiSettings, providerId: string, resourceType: string, limit = 100 ): Promise<{ state: SearchIndexState }> { return apiFetch<{ state: SearchIndexState }>( settings, apiPath( `/api/v1/search/admin/rebuilds/${encodeURIComponent(providerId)}/${encodeURIComponent(resourceType)}/continue`, { limit } ), { method: "POST" } ); }