import { create } from "zustand"; import { api } from "../lib/api.ts"; export interface ConversationMember { id: string; username: string; display_name: string; avatar: string; } export interface Conversation { id: string; type: "dm" | "group_dm"; name: string; members: ConversationMember[]; created_at: string; } export interface ConversationMessage { id: string; conversation_id: string; author_id: string; author_username: string; author_display_name: string | null; content: string; created_at: string; edited_at: string | null; } interface ConversationState { conversations: Conversation[]; activeConversationId: string | null; messagesByConversation: Record; isLoading: boolean; isLoadingOlder: boolean; hasMoreByConversation: Record; error: string | null; fetchConversations: () => Promise; createConversation: (userIds: string[]) => Promise; setActiveConversation: (id: string | null) => void; fetchMessages: (conversationId: string, before?: string) => Promise; fetchOlderMessages: (conversationId: string) => Promise; sendMessage: (conversationId: string, content: string) => Promise; addMessage: (message: ConversationMessage) => void; } export const useConversationStore = create((set, get) => ({ conversations: [], activeConversationId: null, messagesByConversation: {}, isLoading: false, isLoadingOlder: false, hasMoreByConversation: {}, error: null, fetchConversations: async () => { try { const conversations = await api.get("/conversations"); set({ conversations: Array.isArray(conversations) ? conversations : [] }); } catch (error) { set({ error: error instanceof Error ? error.message : "Failed to fetch conversations", }); } }, createConversation: async (userIds) => { const conversation = await api.post("/conversations", { user_ids: userIds }); set((state) => ({ conversations: [conversation, ...state.conversations], activeConversationId: conversation.id, })); return conversation; }, setActiveConversation: (id) => set({ activeConversationId: id }), fetchMessages: async (conversationId, before) => { set({ isLoading: true }); try { const params = before ? "?before=" + encodeURIComponent(before) : ""; const messages = await api.get( `/conversations/${conversationId}/messages${params}`, ); const list = Array.isArray(messages) ? messages : []; set((state) => ({ messagesByConversation: { ...state.messagesByConversation, [conversationId]: list, }, hasMoreByConversation: { ...state.hasMoreByConversation, [conversationId]: list.length >= 50, }, isLoading: false, })); } catch (error) { set({ isLoading: false, error: error instanceof Error ? error.message : "Failed" }); } }, fetchOlderMessages: async (conversationId) => { const state = get(); if (state.isLoadingOlder || state.hasMoreByConversation[conversationId] === false) return; const existing = state.messagesByConversation[conversationId] || []; if (existing.length === 0) return; const oldestId = existing[0].id; set({ isLoadingOlder: true }); try { const older = await api.get( `/conversations/${conversationId}/messages?before=${encodeURIComponent(oldestId)}`, ); const list = Array.isArray(older) ? older : []; set((state) => ({ messagesByConversation: { ...state.messagesByConversation, [conversationId]: [...list, ...existing], }, hasMoreByConversation: { ...state.hasMoreByConversation, [conversationId]: list.length >= 50, }, isLoadingOlder: false, })); } catch { set({ isLoadingOlder: false }); } }, sendMessage: async (conversationId, content) => { const message = await api.post( `/conversations/${conversationId}/messages`, { content }, ); set((state) => ({ messagesByConversation: { ...state.messagesByConversation, [conversationId]: [ ...(state.messagesByConversation[conversationId] || []), message, ], }, })); return message; }, addMessage: (message) => { set((state) => ({ messagesByConversation: { ...state.messagesByConversation, [message.conversation_id]: [ ...(state.messagesByConversation[message.conversation_id] || []), message, ], }, })); }, }));