'use server'; import { createClient } from '@/lib/supabase/server'; interface TrackApiUsageParams { userId: string; apiType: 'google_search' | 'gemini_ai'; endpoint?: string; success: boolean; errorMessage?: string; } interface ApiStats { totalCalls: number; successfulCalls: number; failedCalls: number; todayCalls: number; googleSearchCalls: number; geminiAiCalls: number; } interface DailyLimitCheck { allowed: boolean; remaining: number; limit: number; } const GOOGLE_SEARCH_DAILY_LIMIT = 80; /** * Track an API usage event */ export async function trackApiUsage(params: TrackApiUsageParams): Promise<{ success: boolean; error?: string }> { try { const supabase = await createClient(); // Security check: Ensure user is only tracking their own usage const { data: { user } } = await supabase.auth.getUser(); if (!user || user.id !== params.userId) { console.error('Unauthorized API tracking attempt'); return { success: false, error: 'Nicht autorisiert' }; } const { error } = await supabase .from('api_usage') .insert({ user_id: params.userId, api_type: params.apiType, endpoint: params.endpoint, success: params.success, error_message: params.errorMessage, }); if (error) { console.error('Failed to track API usage:', error); return { success: false, error: error.message }; } return { success: true }; } catch (err) { console.error('Error tracking API usage:', err); return { success: false, error: 'Failed to track API usage' }; } } /** * Check if daily limit has been reached for a specific API type */ export async function checkDailyLimit(apiType: 'google_search' | 'gemini_ai'): Promise { try { const supabase = await createClient(); // Only enforce limit for Google Search if (apiType !== 'google_search') { return { allowed: true, remaining: 999999, limit: 999999 }; } // Get today's date in Europe/Berlin timezone const today = new Date(); const berlinDate = new Date(today.toLocaleString('en-US', { timeZone: 'Europe/Berlin' })); const startOfDay = new Date(berlinDate); startOfDay.setHours(0, 0, 0, 0); const endOfDay = new Date(berlinDate); endOfDay.setHours(23, 59, 59, 999); const { count, error } = await supabase .from('api_usage') .select('*', { count: 'exact', head: true }) .eq('api_type', apiType) .gte('created_at', startOfDay.toISOString()) .lte('created_at', endOfDay.toISOString()); if (error) { console.error('Error checking daily limit:', error); // Allow on error to avoid blocking users return { allowed: true, remaining: GOOGLE_SEARCH_DAILY_LIMIT, limit: GOOGLE_SEARCH_DAILY_LIMIT }; } const currentCount = count || 0; const remaining = Math.max(0, GOOGLE_SEARCH_DAILY_LIMIT - currentCount); const allowed = currentCount < GOOGLE_SEARCH_DAILY_LIMIT; return { allowed, remaining, limit: GOOGLE_SEARCH_DAILY_LIMIT }; } catch (err) { console.error('Error in checkDailyLimit:', err); // Allow on error return { allowed: true, remaining: GOOGLE_SEARCH_DAILY_LIMIT, limit: GOOGLE_SEARCH_DAILY_LIMIT }; } } /** * Get API usage statistics for a specific user */ export async function getUserApiStats(userId: string): Promise { try { const supabase = await createClient(); const { data, error } = await supabase .from('api_usage') .select('*') .eq('user_id', userId); if (error) { console.error('Error fetching user API stats:', error); return null; } const today = new Date(); const berlinDate = new Date(today.toLocaleString('en-US', { timeZone: 'Europe/Berlin' })); const startOfDay = new Date(berlinDate); startOfDay.setHours(0, 0, 0, 0); const todayData = data.filter(item => new Date(item.created_at) >= startOfDay); return { totalCalls: data.length, successfulCalls: data.filter(item => item.success).length, failedCalls: data.filter(item => !item.success).length, todayCalls: todayData.length, googleSearchCalls: data.filter(item => item.api_type === 'google_search').length, geminiAiCalls: data.filter(item => item.api_type === 'gemini_ai').length, }; } catch (err) { console.error('Error in getUserApiStats:', err); return null; } } /** * Get global API usage statistics (admin only) */ export async function getGlobalApiStats(): Promise { try { const supabase = await createClient(); // Check if user is admin const { data: { user } } = await supabase.auth.getUser(); if (!user) return null; const isAdmin = await checkIsAdmin(user.id); if (!isAdmin) return null; const { data, error } = await supabase .from('api_usage') .select('*'); if (error) { console.error('Error fetching global API stats:', error); return null; } const today = new Date(); const berlinDate = new Date(today.toLocaleString('en-US', { timeZone: 'Europe/Berlin' })); const startOfDay = new Date(berlinDate); startOfDay.setHours(0, 0, 0, 0); const todayData = data.filter(item => new Date(item.created_at) >= startOfDay); return { totalCalls: data.length, successfulCalls: data.filter(item => item.success).length, failedCalls: data.filter(item => !item.success).length, todayCalls: todayData.length, googleSearchCalls: data.filter(item => item.api_type === 'google_search').length, geminiAiCalls: data.filter(item => item.api_type === 'gemini_ai').length, }; } catch (err) { console.error('Error in getGlobalApiStats:', err); return null; } } /** * Check if a user is an admin */ export async function checkIsAdmin(userId: string): Promise { try { console.log('[checkIsAdmin] Checking admin status for user:', userId); const supabase = await createClient(); const { data, error } = await supabase .from('admin_users') .select('role') .eq('user_id', userId) .single(); console.log('[checkIsAdmin] Query result - data:', data, 'error:', error); if (error) { console.log('[checkIsAdmin] Error occurred:', error.message); return false; } const isAdmin = !!data; console.log('[checkIsAdmin] Final result:', isAdmin); return isAdmin; } catch (err) { console.error('[checkIsAdmin] Exception:', err); return false; } }