package chats.data.repository import chats.data.remote.dto.* import chats.domain.model.* // Mappers fun ChatDto.toDomain(currentUserId: String, baseUrl: String): Chat { val chatName = name ?: if (type == "personal") { members.firstOrNull { it.userId != currentUserId }?.user?.displayName ?: "Unknown Chat" } else "Group Chat" val chatAvatar = (avatar ?: if (type == "personal") { members.firstOrNull { it.userId != currentUserId }?.user?.avatarUrl } else null)?.ensureAbsoluteUrl(baseUrl) return Chat( id = id, type = type, name = chatName, avatar = chatAvatar, unreadCount = unreadCount, lastMessage = messages.firstOrNull()?.toDomain(currentUserId, baseUrl) ) } fun Message.toEntity(gson: com.google.gson.Gson): core.database.data.MessageEntity { return core.database.data.MessageEntity( id = id, chatId = chatId, senderId = senderId, senderName = senderName, senderAvatar = senderAvatar, content = content, sequenceId = sequenceId, createdAt = createdAt, mediaType = mediaType.name.lowercase(), mediaJson = gson.toJson(media), reactionsJson = gson.toJson(reactions), isRead = isRead, replyToId = replyTo?.id ) } fun MessageDto.toDomain(currentUserId: String, baseUrl: String): Message { val domainMediaType = when (type) { "gif" -> MediaType.GIF "image", "photo" -> MediaType.IMAGE "video" -> MediaType.VIDEO "audio", "voice" -> MediaType.AUDIO "file" -> MediaType.FILE else -> when (media.firstOrNull()?.type) { "image", "photo" -> MediaType.IMAGE "video" -> MediaType.VIDEO "audio", "voice" -> MediaType.AUDIO "file" -> MediaType.FILE else -> MediaType.TEXT } } return Message( id = id, chatId = chatId ?: "", senderId = senderId ?: "", senderName = sender?.displayName ?: "Unknown", senderAvatar = sender?.avatarUrl?.ensureAbsoluteUrl(baseUrl), content = content, sequenceId = sequenceId ?: 0, createdAt = createdAt ?: "", media = media.map { chats.domain.model.Media( id = it.id ?: java.util.UUID.randomUUID().toString(), type = it.type ?: "unknown", url = (it.url ?: "").ensureAbsoluteUrl(baseUrl), filename = it.filename, size = it.size, duration = it.duration ) }, mediaType = domainMediaType, reactions = reactions?.associate { it.emoji to it.count } ?: emptyMap(), isRead = senderId == currentUserId, isPinned = isPinned ?: false, isForwarded = forwardedFromId != null, forwardedFromName = forwardedFrom?.displayName ?: forwardedFrom?.username, replyTo = replyTo?.toDomain(currentUserId, baseUrl) ) } fun MessageDto.toEntity(baseUrl: String, currentUserId: String, gson: com.google.gson.Gson): core.database.data.MessageEntity { return core.database.data.MessageEntity( id = id, chatId = chatId ?: "", senderId = senderId ?: "", senderName = sender?.displayName ?: "Unknown", senderAvatar = sender?.avatarUrl?.ensureAbsoluteUrl(baseUrl), content = content, sequenceId = sequenceId ?: 0, createdAt = createdAt ?: "", mediaType = type ?: "text", mediaJson = gson.toJson(media), reactionsJson = gson.toJson(reactions), isRead = senderId == currentUserId, replyToId = replyTo?.id ) } fun core.database.data.MessageEntity.toDomain(baseUrl: String, gson: com.google.gson.Gson): Message { val mediaTypeEnum = when (mediaType) { "gif" -> MediaType.GIF "image", "photo" -> MediaType.IMAGE "video" -> MediaType.VIDEO "audio", "voice" -> MediaType.AUDIO "file" -> MediaType.FILE else -> MediaType.TEXT } val mediaTypeToken = object : com.google.gson.reflect.TypeToken>() {}.type val mediaDtos: List = try { gson.fromJson(mediaJson, mediaTypeToken) } catch (e: Exception) { emptyList() } ?: emptyList() val reactionsTypeToken = object : com.google.gson.reflect.TypeToken>() {}.type val reactionDtos: List = try { gson.fromJson(reactionsJson, reactionsTypeToken) } catch (e: Exception) { try { val mapType = object : com.google.gson.reflect.TypeToken>() {}.type val map: Map = gson.fromJson(reactionsJson, mapType) ?: emptyMap() map.map { chats.data.remote.dto.ReactionDto(it.key, it.value, false) } } catch (innerE: Exception) { emptyList() } } ?: emptyList() return Message( id = id, chatId = chatId, senderId = senderId, senderName = senderName, senderAvatar = senderAvatar, content = content, sequenceId = sequenceId, createdAt = createdAt, media = mediaDtos.map { chats.domain.model.Media( id = it.id ?: java.util.UUID.randomUUID().toString(), type = it.type ?: "unknown", url = (it.url ?: "").ensureAbsoluteUrl(baseUrl), filename = it.filename, size = it.size, duration = it.duration ) }, mediaType = mediaTypeEnum, reactions = reactionDtos.associate { it.emoji to it.count }, isRead = isRead ) } fun String.ensureAbsoluteUrl(baseUrl: String): String { return if (this.startsWith("http")) { this } else { val base = baseUrl.removeSuffix("/") val path = if (this.startsWith("/")) this else "/$this" "$base$path" } }