import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { supabase } from '@/integrations/supabase/client'; import { toast } from 'sonner'; export interface AlertConfig { id: string; metric_type: 'block_rate' | 'total_requests' | 'unique_ips' | 'function_specific'; threshold_value: number; time_window_ms: number; function_name?: string; enabled: boolean; created_at: string; updated_at: string; } export interface Alert { id: string; config_id: string; metric_type: string; metric_value: number; threshold_value: number; time_window_ms: number; function_name?: string; alert_message: string; resolved_at?: string; created_at: string; } export function useAlertConfigs() { return useQuery({ queryKey: ['rateLimitAlertConfigs'], queryFn: async () => { const { data, error } = await supabase .from('rate_limit_alert_config') .select('*') .order('metric_type'); if (error) throw error; return data as AlertConfig[]; }, }); } export function useAlertHistory(limit: number = 50) { return useQuery({ queryKey: ['rateLimitAlerts', limit], queryFn: async () => { const { data, error } = await supabase .from('rate_limit_alerts') .select('*') .order('created_at', { ascending: false }) .limit(limit); if (error) throw error; return data as Alert[]; }, refetchInterval: 30000, // Refetch every 30 seconds }); } export function useUnresolvedAlerts() { return useQuery({ queryKey: ['rateLimitAlertsUnresolved'], queryFn: async () => { const { data, error } = await supabase .from('rate_limit_alerts') .select('*') .is('resolved_at', null) .order('created_at', { ascending: false }); if (error) throw error; return data as Alert[]; }, refetchInterval: 15000, // Refetch every 15 seconds }); } export function useUpdateAlertConfig() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async ({ id, updates }: { id: string; updates: Partial }) => { // Fetch old config for audit log const { data: oldConfig } = await supabase .from('rate_limit_alert_config') .select('*') .eq('id', id) .single(); const { data, error } = await supabase .from('rate_limit_alert_config') .update(updates) .eq('id', id) .select() .single(); if (error) throw error; return { data, oldConfig }; }, onSuccess: async ({ data, oldConfig }) => { queryClient.invalidateQueries({ queryKey: ['rateLimitAlertConfigs'] }); // Log to audit trail const { logAdminAction } = await import('@/lib/adminActionAuditHelpers'); await logAdminAction('rate_limit_config_updated', { config_id: data.id, metric_type: data.metric_type, old_threshold: oldConfig?.threshold_value, new_threshold: data.threshold_value, old_enabled: oldConfig?.enabled, new_enabled: data.enabled, function_name: data.function_name, }); toast.success('Alert configuration updated'); }, onError: (error) => { toast.error(`Failed to update alert config: ${error.message}`); }, }); } export function useCreateAlertConfig() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (config: Omit) => { const { data, error } = await supabase .from('rate_limit_alert_config') .insert(config) .select() .single(); if (error) throw error; return data; }, onSuccess: async (data) => { queryClient.invalidateQueries({ queryKey: ['rateLimitAlertConfigs'] }); // Log to audit trail const { logAdminAction } = await import('@/lib/adminActionAuditHelpers'); await logAdminAction('rate_limit_config_created', { config_id: data.id, metric_type: data.metric_type, threshold_value: data.threshold_value, time_window_ms: data.time_window_ms, function_name: data.function_name, enabled: data.enabled, }); toast.success('Alert configuration created'); }, onError: (error) => { toast.error(`Failed to create alert config: ${error.message}`); }, }); } export function useDeleteAlertConfig() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (id: string) => { // Fetch config details before deletion for audit log const { data: config } = await supabase .from('rate_limit_alert_config') .select('*') .eq('id', id) .single(); const { error } = await supabase .from('rate_limit_alert_config') .delete() .eq('id', id); if (error) throw error; return config; }, onSuccess: async (config) => { queryClient.invalidateQueries({ queryKey: ['rateLimitAlertConfigs'] }); // Log to audit trail if (config) { const { logAdminAction } = await import('@/lib/adminActionAuditHelpers'); await logAdminAction('rate_limit_config_deleted', { config_id: config.id, metric_type: config.metric_type, threshold_value: config.threshold_value, time_window_ms: config.time_window_ms, function_name: config.function_name, }); } toast.success('Alert configuration deleted'); }, onError: (error) => { toast.error(`Failed to delete alert config: ${error.message}`); }, }); } export function useResolveAlert() { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (id: string) => { // Fetch full alert details before resolving const { data: alert, error: fetchError } = await supabase .from('rate_limit_alerts') .select('*') .eq('id', id) .single(); if (fetchError) throw fetchError; // Resolve the alert const { data, error } = await supabase .from('rate_limit_alerts') .update({ resolved_at: new Date().toISOString() }) .eq('id', id) .select() .single(); if (error) throw error; // Log to audit trail const { logAdminAction } = await import('@/lib/adminActionAuditHelpers'); await logAdminAction('rate_limit_alert_resolved', { alert_id: id, metric_type: alert.metric_type, metric_value: alert.metric_value, threshold_value: alert.threshold_value, function_name: alert.function_name, time_window_ms: alert.time_window_ms, }); return data; }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['rateLimitAlerts'] }); queryClient.invalidateQueries({ queryKey: ['rateLimitAlertsUnresolved'] }); toast.success('Alert resolved'); }, onError: (error) => { toast.error(`Failed to resolve alert: ${error.message}`); }, }); }