// (c) 2026 TWWIM UG. All rights reserved. (www.twwim.com) import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { queryKeys } from '@/lib/query-keys'; import { knowledgeApi } from '@/infrastructure/http/api/knowledge'; import type { CreateEntryInput, KnowledgeDocument, KnowledgeDocumentList } from '@/infrastructure/http/api/knowledge'; import { KnowledgeMapper } from '@/application/mappers/KnowledgeMapper'; import type { KnowledgeListResult } from '@/application/mappers/KnowledgeMapper'; import type { KnowledgeEntry } from '@/domain/entities/KnowledgeEntry'; export function useKnowledgeEntries(tenantId: string, params?: { type?: string; limit?: number; offset?: string }) { return useQuery({ queryKey: queryKeys.knowledge.list(tenantId, params), queryFn: async () => { const result = await knowledgeApi.listEntries(tenantId, params); return KnowledgeMapper.toDomainList(result); }, enabled: !!tenantId, }); } export function useKnowledgeEntry(tenantId: string, id: string) { return useQuery({ queryKey: queryKeys.knowledge.detail(tenantId, id), queryFn: async () => { const point = await knowledgeApi.getEntry(tenantId, id); return KnowledgeMapper.toDomain(point); }, enabled: !!tenantId && !!id, }); } export function useKnowledgeStats(tenantId: string) { return useQuery({ queryKey: queryKeys.knowledge.stats(tenantId), queryFn: () => knowledgeApi.getStats(tenantId), enabled: !!tenantId, }); } export function useCreateKnowledgeEntry(tenantId: string) { const queryClient = useQueryClient(); return useMutation({ mutationFn: (input: CreateEntryInput) => knowledgeApi.createEntry(tenantId, input), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.knowledge.lists() }); queryClient.invalidateQueries({ queryKey: queryKeys.knowledge.stats(tenantId) }); }, }); } export function useDeleteKnowledgeEntry(tenantId: string) { const queryClient = useQueryClient(); return useMutation({ mutationFn: (id: string) => knowledgeApi.deleteEntry(tenantId, id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.knowledge.lists() }); queryClient.invalidateQueries({ queryKey: queryKeys.knowledge.stats(tenantId) }); }, }); } export function useSearchKnowledge(tenantId: string) { return useMutation({ mutationFn: (query: string) => knowledgeApi.search(tenantId, query), }); } // ── Documents ──────────────────────────────────────────────────────────── /** * Paginated list of uploaded documents. Polls every 5s while any item is in * a transient state (PENDING/PROCESSING) so status transitions are visible * without manual refresh. */ export function useKnowledgeDocuments(tenantId: string, params?: { limit?: number; offset?: number }) { return useQuery({ queryKey: queryKeys.knowledge.documents(tenantId, params), queryFn: () => knowledgeApi.listDocuments(tenantId, params), enabled: !!tenantId, refetchInterval: (q) => { const data = q.state.data as KnowledgeDocumentList | undefined; const pending = data?.items?.some( (d: KnowledgeDocumentList['items'][number]) => d.status === 'PENDING' || d.status === 'PROCESSING', ); return pending ? 5000 : false; }, }); } export function useKnowledgeDocument(tenantId: string, id: string) { return useQuery({ queryKey: queryKeys.knowledge.document(tenantId, id), queryFn: () => knowledgeApi.getDocument(tenantId, id), enabled: !!tenantId && !!id, refetchInterval: (q) => { const data = q.state.data as KnowledgeDocument | undefined; return data?.status === 'PENDING' || data?.status === 'PROCESSING' ? 3000 : false; }, }); } export function useUploadKnowledgeDocument(tenantId: string) { const queryClient = useQueryClient(); return useMutation({ mutationFn: (file: File) => knowledgeApi.uploadDocument(tenantId, file), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.knowledge.documentLists(tenantId) }); queryClient.invalidateQueries({ queryKey: queryKeys.knowledge.stats(tenantId) }); }, }); } export function useDeleteKnowledgeDocument(tenantId: string) { const queryClient = useQueryClient(); return useMutation({ mutationFn: (id: string) => knowledgeApi.deleteDocument(tenantId, id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: queryKeys.knowledge.documentLists(tenantId) }); queryClient.invalidateQueries({ queryKey: queryKeys.knowledge.stats(tenantId) }); }, }); }