package chats.data.local.dao import androidx.room.* import chats.data.local.database.MessageEntity import chats.domain.model.MessageStatus import kotlinx.coroutines.flow.Flow /** * DAO для операций с сообщениями в Room Database */ @Dao interface MessageDao { @Query("SELECT * FROM messages WHERE chatId = :chatId ORDER BY sequenceId ASC") fun getMessagesByChatId(chatId: String): Flow> /** * Пагинированная загрузка сообщений для Paging 3 * sequenceId увеличивается от старых к новым, поэтому ORDER BY DESC для отображения newest внизу */ @Query("SELECT * FROM messages WHERE chatId = :chatId ORDER BY sequenceId DESC LIMIT :limit OFFSET :offset") suspend fun getMessagesPaged(chatId: String, offset: Int, limit: Int): List @Query("SELECT * FROM messages WHERE chatId = :chatId ORDER BY sequenceId DESC LIMIT 1") suspend fun getLastMessage(chatId: String): MessageEntity? @Query("SELECT * FROM messages WHERE chatId = :chatId ORDER BY sequenceId ASC LIMIT 1") suspend fun getFirstMessage(chatId: String): MessageEntity? @Query("SELECT * FROM messages WHERE chatId = :chatId AND sequenceId > :afterSequenceId ORDER BY sequenceId ASC LIMIT :limit") suspend fun getMessagesAfter(chatId: String, afterSequenceId: Long, limit: Int): List @Query("SELECT * FROM messages WHERE chatId = :chatId AND sequenceId < :beforeSequenceId ORDER BY sequenceId DESC LIMIT :limit") suspend fun getMessagesBefore(chatId: String, beforeSequenceId: Long, limit: Int): List @Query("SELECT * FROM messages WHERE localId = :localId") suspend fun getMessageByLocalId(localId: String): MessageEntity? @Query("SELECT * FROM messages WHERE serverId = :serverId") suspend fun getMessageByServerId(serverId: String): MessageEntity? @Query("SELECT * FROM messages WHERE status IN (:statuses) AND chatId = :chatId") suspend fun getMessagesByStatus(chatId: String, statuses: List): List @Query("SELECT * FROM messages WHERE status = :status") fun getMessagesByStatusFlow(status: MessageStatus): Flow> @Query("SELECT * FROM messages WHERE status IN (:statuses)") suspend fun getPendingMessages(statuses: List): List @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertMessage(message: MessageEntity) @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertMessages(messages: List) @Update suspend fun updateMessage(message: MessageEntity) @Delete suspend fun deleteMessage(message: MessageEntity) @Query("DELETE FROM messages WHERE localId = :localId") suspend fun deleteMessageByLocalId(localId: String) @Query("DELETE FROM messages WHERE chatId = :chatId") suspend fun deleteMessagesByChatId(chatId: String) @Query("UPDATE messages SET status = :status, updatedAtMillis = :updatedAtMillis WHERE localId = :localId") suspend fun updateMessageStatus(localId: String, status: MessageStatus, updatedAtMillis: Long) @Query("UPDATE messages SET serverId = :serverId, status = :status, updatedAtMillis = :updatedAtMillis WHERE localId = :localId") suspend fun updateMessageWithServerId(localId: String, serverId: String, status: MessageStatus, updatedAtMillis: Long) @Query("UPDATE messages SET status = :status, errorMessage = :errorMessage, retryCount = retryCount + 1, updatedAtMillis = :updatedAtMillis WHERE localId = :localId") suspend fun updateMessageError(localId: String, status: MessageStatus, errorMessage: String, updatedAtMillis: Long) @Query("SELECT COUNT(*) FROM messages WHERE chatId = :chatId AND status IN (:statuses)") suspend fun getUnsentCount(chatId: String, statuses: List): Int @Query("SELECT * FROM messages WHERE chatId = :chatId AND status = :status LIMIT 1") suspend fun getFirstMessageByStatus(chatId: String, status: MessageStatus): MessageEntity? }