'use client' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { getEnterpriseClients, getEnterpriseClient, createEnterpriseClient, updateEnterpriseClient, deleteEnterpriseClient, getClientServers, getClientServer, addClientServer, updateClientServer, removeClientServer, testServerPortainerConnection, performServerAction, requestVerificationCode, getErrorRules, createErrorRule, updateErrorRule, deleteErrorRule, getDetectedErrors, acknowledgeError, getClientStats, getServerStats, collectServerStats, getServerContainers, getContainer, getContainerLogs, performContainerAction, removeContainer, getErrorDashboard, getContainerEvents, acknowledgeContainerEvents, getErrorSummary, getNotificationSettings, updateNotificationSettings, } from '@/lib/api/admin' import type { StatsRange, ContainerEventFilters, UpdateNotificationSettingsPayload } from '@/lib/api/admin' import type { CreateEnterpriseClientPayload, UpdateEnterpriseClientPayload, AddServerPayload, UpdateServerPayload, ServerActionPayload, CreateErrorRulePayload, UpdateErrorRulePayload, ErrorFilters, } from '@/types/api' // ============================================================================ // Query Keys // ============================================================================ export const enterpriseClientKeys = { all: ['enterprise-clients'] as const, lists: () => [...enterpriseClientKeys.all, 'list'] as const, list: () => [...enterpriseClientKeys.lists()] as const, details: () => [...enterpriseClientKeys.all, 'detail'] as const, detail: (id: string) => [...enterpriseClientKeys.details(), id] as const, servers: (clientId: string) => [...enterpriseClientKeys.detail(clientId), 'servers'] as const, server: (clientId: string, serverId: string) => [...enterpriseClientKeys.servers(clientId), serverId] as const, serverStats: (clientId: string, serverId: string, range: StatsRange) => [...enterpriseClientKeys.server(clientId, serverId), 'stats', range] as const, clientStats: (clientId: string, range: StatsRange) => [...enterpriseClientKeys.detail(clientId), 'stats', range] as const, errorRules: (clientId: string) => [...enterpriseClientKeys.detail(clientId), 'error-rules'] as const, errors: (clientId: string, filters?: ErrorFilters) => [...enterpriseClientKeys.detail(clientId), 'errors', filters] as const, containers: (clientId: string, serverId: string) => [...enterpriseClientKeys.server(clientId, serverId), 'containers'] as const, container: (clientId: string, serverId: string, containerId: string) => [...enterpriseClientKeys.containers(clientId, serverId), containerId] as const, containerLogs: (clientId: string, serverId: string, containerId: string, tail: number) => [...enterpriseClientKeys.container(clientId, serverId, containerId), 'logs', tail] as const, // Error tracking keys errorDashboard: (clientId: string) => [...enterpriseClientKeys.detail(clientId), 'error-dashboard'] as const, containerEvents: (clientId: string, filters?: ContainerEventFilters) => [...enterpriseClientKeys.detail(clientId), 'container-events', filters] as const, errorSummary: () => [...enterpriseClientKeys.all, 'error-summary'] as const, // Notification settings key notifications: (clientId: string) => [...enterpriseClientKeys.detail(clientId), 'notifications'] as const, } // ============================================================================ // Client Hooks // ============================================================================ export function useEnterpriseClients() { return useQuery({ queryKey: enterpriseClientKeys.list(), queryFn: getEnterpriseClients, }) } export function useEnterpriseClient(id: string) { return useQuery({ queryKey: enterpriseClientKeys.detail(id), queryFn: () => getEnterpriseClient(id), enabled: !!id, }) } export function useCreateEnterpriseClient() { const queryClient = useQueryClient() return useMutation({ mutationFn: (data: CreateEnterpriseClientPayload) => createEnterpriseClient(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.lists() }) }, }) } export function useUpdateEnterpriseClient() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ id, data }: { id: string; data: UpdateEnterpriseClientPayload }) => updateEnterpriseClient(id, data), onSuccess: (_, { id }) => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.detail(id) }) queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.lists() }) }, }) } export function useDeleteEnterpriseClient() { const queryClient = useQueryClient() return useMutation({ mutationFn: (id: string) => deleteEnterpriseClient(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.lists() }) }, }) } // ============================================================================ // Server Hooks // ============================================================================ export function useClientServers(clientId: string) { return useQuery({ queryKey: enterpriseClientKeys.servers(clientId), queryFn: () => getClientServers(clientId), enabled: !!clientId, }) } export function useClientServer(clientId: string, serverId: string) { return useQuery({ queryKey: enterpriseClientKeys.server(clientId, serverId), queryFn: () => getClientServer(clientId, serverId), enabled: !!clientId && !!serverId, }) } export function useAddServerToClient() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, data }: { clientId: string; data: AddServerPayload }) => addClientServer(clientId, data), onSuccess: (_, { clientId }) => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.servers(clientId) }) queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.detail(clientId) }) }, }) } export function useUpdateClientServer() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, serverId, data, }: { clientId: string serverId: string data: UpdateServerPayload }) => updateClientServer(clientId, serverId, data), onSuccess: (_, { clientId, serverId }) => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.server(clientId, serverId) }) queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.servers(clientId) }) }, }) } export function useRemoveServerFromClient() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, serverId }: { clientId: string; serverId: string }) => removeClientServer(clientId, serverId), onSuccess: (_, { clientId }) => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.servers(clientId) }) queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.detail(clientId) }) }, }) } export function useTestPortainerConnection() { return useMutation({ mutationFn: ({ clientId, serverId, credentials, }: { clientId: string serverId: string credentials: { portainerUrl: string; portainerUsername: string; portainerPassword: string } }) => testServerPortainerConnection(clientId, serverId, credentials), }) } // ============================================================================ // Server Action Hooks // ============================================================================ export function useServerAction() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, serverId, action, }: { clientId: string serverId: string action: ServerActionPayload }) => performServerAction(clientId, serverId, action), onSuccess: (_, { clientId, serverId }) => { // Refresh server status after action queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.server(clientId, serverId) }) queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.servers(clientId) }) }, }) } export function useRequestVerificationCode() { return useMutation({ mutationFn: ({ clientId, serverId, action, }: { clientId: string serverId: string action: 'WIPE' | 'REINSTALL' }) => requestVerificationCode(clientId, serverId, action), }) } // ============================================================================ // Error Rule Hooks // ============================================================================ export function useErrorRules(clientId: string) { return useQuery({ queryKey: enterpriseClientKeys.errorRules(clientId), queryFn: () => getErrorRules(clientId), enabled: !!clientId, }) } export function useCreateErrorRule() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, data }: { clientId: string; data: CreateErrorRulePayload }) => createErrorRule(clientId, data), onSuccess: (_, { clientId }) => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.errorRules(clientId) }) }, }) } export function useUpdateErrorRule() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, ruleId, data, }: { clientId: string ruleId: string data: UpdateErrorRulePayload }) => updateErrorRule(clientId, ruleId, data), onSuccess: (_, { clientId }) => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.errorRules(clientId) }) }, }) } export function useDeleteErrorRule() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, ruleId }: { clientId: string; ruleId: string }) => deleteErrorRule(clientId, ruleId), onSuccess: (_, { clientId }) => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.errorRules(clientId) }) }, }) } // ============================================================================ // Detected Error Hooks // ============================================================================ export function useDetectedErrors(clientId: string, filters?: ErrorFilters) { return useQuery({ queryKey: enterpriseClientKeys.errors(clientId, filters), queryFn: () => getDetectedErrors(clientId, filters), enabled: !!clientId, }) } export function useAcknowledgeError() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, errorId }: { clientId: string; errorId: string }) => acknowledgeError(clientId, errorId), onSuccess: (_, { clientId }) => { // Invalidate all error queries for this client queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.detail(clientId), predicate: (query) => { const key = query.queryKey return Array.isArray(key) && key.includes('errors') }, }) // Also refresh the client detail to update error count queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.detail(clientId) }) }, }) } // ============================================================================ // Stats Hooks // ============================================================================ export function useClientStatsOverview(clientId: string, range: StatsRange = '24h') { return useQuery({ queryKey: enterpriseClientKeys.clientStats(clientId, range), queryFn: () => getClientStats(clientId, range), enabled: !!clientId, refetchInterval: 60000, // Refresh every minute }) } export function useServerStatsHistory( clientId: string, serverId: string, range: StatsRange = '24h' ) { return useQuery({ queryKey: enterpriseClientKeys.serverStats(clientId, serverId, range), queryFn: () => getServerStats(clientId, serverId, range), enabled: !!clientId && !!serverId, refetchInterval: 30000, // Refresh every 30 seconds }) } export function useCollectServerStats() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, serverId }: { clientId: string; serverId: string }) => collectServerStats(clientId, serverId), onSuccess: (_, { clientId, serverId }) => { // Invalidate all stats queries for this server queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.server(clientId, serverId), }) }, }) } // ============================================================================ // Container Hooks // ============================================================================ export function useServerContainers(clientId: string, serverId: string, all: boolean = true) { return useQuery({ queryKey: enterpriseClientKeys.containers(clientId, serverId), queryFn: () => getServerContainers(clientId, serverId, all), enabled: !!clientId && !!serverId, refetchInterval: 10000, // Refresh every 10 seconds }) } export function useContainer(clientId: string, serverId: string, containerId: string) { return useQuery({ queryKey: enterpriseClientKeys.container(clientId, serverId, containerId), queryFn: () => getContainer(clientId, serverId, containerId), enabled: !!clientId && !!serverId && !!containerId, }) } export function useContainerLogs( clientId: string, serverId: string, containerId: string, tail: number = 500 ) { return useQuery({ queryKey: enterpriseClientKeys.containerLogs(clientId, serverId, containerId, tail), queryFn: () => getContainerLogs(clientId, serverId, containerId, tail), enabled: !!clientId && !!serverId && !!containerId, }) } export function useContainerAction() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, serverId, containerId, action, }: { clientId: string serverId: string containerId: string action: 'start' | 'stop' | 'restart' }) => performContainerAction(clientId, serverId, containerId, action), onSuccess: (_, { clientId, serverId }) => { // Invalidate container list to refresh status queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.containers(clientId, serverId), }) }, }) } export function useRemoveContainer() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, serverId, containerId, force, }: { clientId: string serverId: string containerId: string force?: boolean }) => removeContainer(clientId, serverId, containerId, force), onSuccess: (_, { clientId, serverId }) => { // Invalidate container list queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.containers(clientId, serverId), }) }, }) } // ============================================================================ // Error Dashboard Hooks // ============================================================================ export function useErrorDashboard(clientId: string) { return useQuery({ queryKey: enterpriseClientKeys.errorDashboard(clientId), queryFn: () => getErrorDashboard(clientId), enabled: !!clientId, refetchInterval: 60000, // Refresh every minute }) } // ============================================================================ // Container Events Hooks // ============================================================================ export function useContainerEvents(clientId: string, filters?: ContainerEventFilters) { return useQuery({ queryKey: enterpriseClientKeys.containerEvents(clientId, filters), queryFn: () => getContainerEvents(clientId, filters), enabled: !!clientId, refetchInterval: 30000, // Refresh every 30 seconds }) } export function useAcknowledgeContainerEvents() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, eventIds }: { clientId: string; eventIds: string[] }) => acknowledgeContainerEvents(clientId, eventIds), onSuccess: (_, { clientId }) => { // Invalidate container events queries for this client queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.detail(clientId), predicate: (query) => { const key = query.queryKey return Array.isArray(key) && key.includes('container-events') }, }) // Also refresh the error dashboard queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.errorDashboard(clientId), }) // Also refresh the global error summary queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.errorSummary(), }) }, }) } // ============================================================================ // All Clients Error Summary Hooks // ============================================================================ export function useAllClientsErrorSummary() { return useQuery({ queryKey: enterpriseClientKeys.errorSummary(), queryFn: getErrorSummary, refetchInterval: 60000, // Refresh every minute }) } // ============================================================================ // Notification Settings Hooks // ============================================================================ export function useNotificationSettings(clientId: string) { return useQuery({ queryKey: enterpriseClientKeys.notifications(clientId), queryFn: () => getNotificationSettings(clientId), enabled: !!clientId, }) } export function useUpdateNotificationSettings() { const queryClient = useQueryClient() return useMutation({ mutationFn: ({ clientId, data, }: { clientId: string data: UpdateNotificationSettingsPayload }) => updateNotificationSettings(clientId, data), onSuccess: (_, { clientId }) => { queryClient.invalidateQueries({ queryKey: enterpriseClientKeys.notifications(clientId), }) }, }) }