'use server'; import { createServerClient } from '@/utils/supabase'; import type { Profile, Result } from '@/utils/supabase'; import { getUser, getProfile, getSignedUrl } from '@/lib/actions'; export type UserWithStatus = { id?: string; user: Profile; status: string; created_at: string; updated_by?: Profile; }; type PaginatedHistory = { statuses: UserWithStatus[]; meta: { current_page: number; per_page: number; total_pages: number; total_count: number; }; }; export const getRecentUsersWithStatuses = async (): Promise< Result > => { try { const supabase = await createServerClient(); const oneDayAgo = new Date(Date.now() - 1000 * 60 * 60 * 24); const { data, error } = (await supabase .from('statuses') .select(` user:profiles!user_id(*), status, created_at, updated_by:profiles!updated_by_id(*) `) .gte('created_at', oneDayAgo.toISOString()) .order('created_at', { ascending: false })) as { data: UserWithStatus[]; error: unknown; }; if (error) throw error as Error; if (!data?.length) return { success: true, data: [] }; const seen = new Set(); const filtered = data.filter((row) => { if (seen.has(row.user.id)) return false; seen.add(row.user.id); return true; }); const filteredWithAvatars = new Array(); for (const userWithStatus of filtered) { if (userWithStatus.user.avatar_url) { const avatarResponse = await getSignedUrl({ bucket: 'avatars', url: userWithStatus.user.avatar_url, }); if (avatarResponse.success) { userWithStatus.user.avatar_url = avatarResponse.data; } else userWithStatus.user.avatar_url = null; } else userWithStatus.user.avatar_url = null; if (userWithStatus.updated_by?.avatar_url) { const updatedByAvatarResponse = await getSignedUrl({ bucket: 'avatars', url: userWithStatus.updated_by.avatar_url ?? '', }); if (updatedByAvatarResponse.success) { userWithStatus.updated_by.avatar_url = updatedByAvatarResponse.data; } else userWithStatus.updated_by.avatar_url = null; } else { if (userWithStatus.updated_by) userWithStatus.updated_by.avatar_url = null; } filteredWithAvatars.push(userWithStatus); } return { success: true, data: filteredWithAvatars }; } catch (error) { return { success: false, error: `Error: ${error as Error}` }; } }; export const broadcastStatusUpdates = async ( userStatuses: UserWithStatus[], ): Promise> => { try { const supabase = await createServerClient(); for (const userStatus of userStatuses) { const broadcast = await supabase.channel('status_updates').send({ type: 'broadcast', event: 'status_updated', payload: { user_status: userStatus, timestamp: new Date().toISOString(), }, }); if (broadcast === 'error' || broadcast === 'timed out') throw new Error( 'Failed to broadcast status update. Timed out or errored.', ); } return { success: true, data: undefined }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error', }; } }; export const updateStatuses = async ( userIds: string[], status: string, ): Promise> => { try { const supabase = await createServerClient(); const profileResponse = await getProfile(); if (!profileResponse.success) throw new Error('Not authenticated!'); const userProfile = profileResponse.data; const inserts = userIds.map((userId) => ({ user_id: userId, status, updated_by_id: userProfile.id, })); const { data: insertedStatuses, error: insertedStatusesError } = await supabase.from('statuses').insert(inserts).select(); if (insertedStatusesError) throw insertedStatusesError as Error; if (insertedStatuses) { const broadcastArray = new Array(insertedStatuses.length); for (const insertedStatus of insertedStatuses) { const profileResponse = await getProfile(insertedStatus.user_id) if (!profileResponse.success) throw new Error(profileResponse.error); const profile = profileResponse.data; if (profile) { broadcastArray.push({ user: profile, status: insertedStatus.status, created_at: insertedStatus.created_at, updated_by: userProfile, }); } } await broadcastStatusUpdates(broadcastArray); } return { success: true, data: undefined }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error', }; } }; export const updateUserStatus = async ( status: string, ): Promise> => { try { const supabase = await createServerClient(); const profileResponse = await getProfile(); if (!profileResponse.success) throw new Error(`Not authenticated! ${profileResponse.error}`); const userProfile = profileResponse.data; const { data: insertedStatus, error: insertedStatusError } = await supabase .from('statuses') .insert({ user_id: userProfile.id, status, updated_by_id: userProfile.id, }) .select() .single(); if (insertedStatusError) throw insertedStatusError as Error; const userStatus: UserWithStatus = { user: userProfile, status: insertedStatus.status, created_at: insertedStatus.created_at, updated_by: userProfile, }; await broadcastStatusUpdates([userStatus]); return { success: true, data: undefined }; } catch (error) { return { success: false, error: `Error updating user's status: ${error as Error}`, }; } }; export const getUserHistory = async ( userId: string, page = 1, perPage = 50, ): Promise> => { try { const supabase = await createServerClient(); const userResponse = await getUser(); if (!userResponse.success) throw new Error(`Not authenticated! ${userResponse.error}`); const offset = (page - 1) * perPage; const { count } = await supabase .from('statuses') .select('*', { count: 'exact', head: true }) .eq('user_id', userId); const { data: statuses, error: statusesError } = (await supabase .from('statuses') .select( ` id, user:profiles!user_id(*), status, created_at, updated_by:profiles!updated_by_id(*) `, ) .eq('user_id', userId) .order('created_at', { ascending: false }) .range(offset, offset + perPage - 1)) as { data: UserWithStatus[]; error: unknown; }; if (statusesError) throw statusesError as Error; const totalCount = count ?? 0; const totalPages = Math.ceil(totalCount / perPage); return { success: true, data: { statuses, meta: { current_page: page, per_page: perPage, total_pages: totalPages, total_count: totalCount, }, }, }; } catch (error) { return { success: false, error: `Error getting user's history: ${error as Error}`, }; } }; export const getAllHistory = async ( page = 1, perPage = 50, ): Promise> => { try { const supabase = await createServerClient(); const userResponse = await getUser(); if (!userResponse.success) throw new Error(`Not authenticated! ${userResponse.error}`); const offset = (page - 1) * perPage; const { count } = await supabase .from('statuses') .select('*', { count: 'exact', head: true }); const { data: statuses, error: statusesError } = (await supabase .from('statuses') .select( ` id, user:profiles!user_id(*), status, created_at, updated_by:profiles!updated_by_id(*) `, ) .order('created_at', { ascending: false }) .range(offset, offset + perPage - 1)) as { data: UserWithStatus[]; error: unknown; }; if (statusesError) throw statusesError as Error; const totalCount = count ?? 0; const totalPages = Math.ceil(totalCount / perPage); return { success: true, data: { statuses, meta: { current_page: page, per_page: perPage, total_pages: totalPages, total_count: totalCount, }, }, }; } catch (error) { return { success: false, error: `Error getting all history: ${error as Error}`, }; } };