import type { SupportedLocale } from '../i18n/types.js'; import type { AppSupabaseClient } from '../supabase/client.js'; import type { Database, PresenceState } from '../supabase/types.js'; type ProfileUpdate = Database['public']['Tables']['profiles']['Update']; export interface Profile { userId: string; username: string; displayName: string; avatarUrl: string | null; statusMessage: string | null; presenceState: PresenceState; showReadReceipts: boolean; allowDmsFromStrangers: boolean; isAdmin: boolean; locale: SupportedLocale; } type ProfileRow = { user_id: string; username: string; display_name: string; avatar_url: string | null; status_message: string | null; presence_state: PresenceState; show_read_receipts: boolean; allow_dms_from_strangers: boolean; is_admin: boolean; locale: string; }; const PROFILE_COLS = 'user_id, username, display_name, avatar_url, status_message, presence_state, show_read_receipts, allow_dms_from_strangers, is_admin, locale'; function toSupportedLocale(raw: string): SupportedLocale { return raw === 'de' ? 'de' : 'en'; } function mapProfile(row: ProfileRow): Profile { return { userId: row.user_id, username: row.username, displayName: row.display_name, avatarUrl: row.avatar_url, statusMessage: row.status_message, presenceState: row.presence_state, showReadReceipts: row.show_read_receipts, allowDmsFromStrangers: row.allow_dms_from_strangers, isAdmin: row.is_admin, locale: toSupportedLocale(row.locale), }; } export async function getOwnProfile(client: AppSupabaseClient): Promise { const { data: session } = await client.auth.getUser(); if (!session.user) return null; const { data, error } = await client .from('profiles') .select(PROFILE_COLS) .eq('user_id', session.user.id) .maybeSingle(); if (error) throw error; return data ? mapProfile(data as unknown as ProfileRow) : null; } export async function getProfileByUsername( client: AppSupabaseClient, username: string, ): Promise { const { data, error } = await client .from('profiles') .select(PROFILE_COLS) .eq('username', username.toLowerCase()) .maybeSingle(); if (error) throw error; return data ? mapProfile(data as unknown as ProfileRow) : null; } export async function isUsernameAvailable( client: AppSupabaseClient, username: string, ): Promise { const { count, error } = await client .from('profiles') .select('user_id', { count: 'exact', head: true }) .eq('username', username.toLowerCase()); if (error) throw error; return (count ?? 0) === 0; } export interface UpdateProfileParams { displayName?: string; avatarUrl?: string | null; statusMessage?: string | null; presenceState?: PresenceState; showReadReceipts?: boolean; allowDmsFromStrangers?: boolean; locale?: SupportedLocale; } export async function updateOwnProfile( client: AppSupabaseClient, params: UpdateProfileParams, ): Promise { const { data: session } = await client.auth.getUser(); if (!session.user) throw new Error('not authenticated'); const patch: ProfileUpdate = {}; if (params.displayName !== undefined) patch.display_name = params.displayName; if (params.avatarUrl !== undefined) patch.avatar_url = params.avatarUrl; if (params.statusMessage !== undefined) patch.status_message = params.statusMessage; if (params.presenceState !== undefined) patch.presence_state = params.presenceState; if (params.showReadReceipts !== undefined) patch.show_read_receipts = params.showReadReceipts; if (params.allowDmsFromStrangers !== undefined) { patch.allow_dms_from_strangers = params.allowDmsFromStrangers; } if (params.locale !== undefined) { (patch as ProfileUpdate & { locale?: string }).locale = params.locale; } const { data, error } = await client .from('profiles') .update(patch) .eq('user_id', session.user.id) .select(PROFILE_COLS) .single(); if (error) throw error; return mapProfile(data as unknown as ProfileRow); }