package com.seven.ikar.kotlin.core.realtime

import com.seven.ikar.kotlin.core.model.AndroidAppReleaseDto
import com.seven.ikar.kotlin.core.model.AttachmentDto
import com.seven.ikar.kotlin.core.model.AttachmentKind
import com.seven.ikar.kotlin.core.model.ChatSummaryDto
import com.seven.ikar.kotlin.core.model.ChatType
import com.seven.ikar.kotlin.core.model.CallAnswerDto
import com.seven.ikar.kotlin.core.model.CallConnectedDto
import com.seven.ikar.kotlin.core.model.CallEndedDto
import com.seven.ikar.kotlin.core.model.CallIceCandidateDto
import com.seven.ikar.kotlin.core.model.CallIceServerDto
import com.seven.ikar.kotlin.core.model.CallMediaType
import com.seven.ikar.kotlin.core.model.CallOfferDto
import com.seven.ikar.kotlin.core.model.IncomingCallDto
import com.seven.ikar.kotlin.core.model.MessageDeliveryState
import com.seven.ikar.kotlin.core.model.MessageDto
import com.seven.ikar.kotlin.core.model.MessageReactionDto
import com.seven.ikar.kotlin.core.model.MessageReplyDto
import com.seven.ikar.kotlin.core.model.OutgoingCallDto
import com.seven.ikar.kotlin.core.model.UserSummaryDto

data class RealtimeUserSummaryDto(
    val id: String,
    val username: String,
    val displayName: String,
    val isOnline: Boolean,
    val phoneNumber: String? = null,
    val lastSeenAt: String? = null,
    val about: String? = null,
    val avatarPath: String? = null,
    val isBot: Boolean = false
)

data class RealtimeAttachmentDto(
    val id: String,
    val fileName: String,
    val contentType: String,
    val fileSizeBytes: Long,
    val downloadPath: String,
    val kind: Int,
    val sortOrder: Int = 0
)

data class RealtimeMessageDto(
    val id: String,
    val chatId: String,
    val chatType: Int,
    val sender: RealtimeUserSummaryDto,
    val text: String,
    val attachments: List<RealtimeAttachmentDto> = emptyList(),
    val sentAt: String,
    val editedAt: String? = null,
    val deletedAt: String? = null,
    val deliveryState: Int,
    val forwardedFromDisplayName: String? = null,
    val replyTo: RealtimeMessageReplyDto? = null,
    val pinnedAt: String? = null,
    val pinnedBy: RealtimeUserSummaryDto? = null,
    val mediaAlbumId: String? = null,
    val reactions: List<RealtimeMessageReactionDto> = emptyList(),
    val hasProtectedContent: Boolean = false,
    val expiresAt: String? = null,
    val ttlSeconds: Int? = null,
    val postedAsChannel: Boolean = false,
    val displayAuthorName: String? = null,
    val viewCount: Int? = null
)

data class RealtimeMessageReplyDto(
    val messageId: String,
    val senderId: String,
    val senderDisplayName: String,
    val previewText: String
)

data class RealtimeMessageReactionDto(
    val emoji: String,
    val count: Int,
    val isMine: Boolean
)

data class RealtimeChatSummaryDto(
    val id: String,
    val title: String,
    val type: Int,
    val secondaryText: String? = null,
    val lastActivityAt: String? = null,
    val lastMessagePreview: String? = null,
    val participants: List<RealtimeUserSummaryDto> = emptyList(),
    val canSendMessages: Boolean = true,
    val unreadCount: Int = 0,
    val isPinned: Boolean = false,
    val isArchived: Boolean = false,
    val isMuted: Boolean = false,
    val folderKey: String? = null,
    val hasProtectedContent: Boolean = false,
    val defaultMessageTtlSeconds: Int? = null,
    val lastMessageAttachment: RealtimeAttachmentDto? = null,
    val subscriberCount: Int = 0,
    val adminCount: Int = 0,
    val isSubscribed: Boolean = false,
    val canSubscribe: Boolean = false,
    val canManageChannel: Boolean = false,
    val canPostAsChannel: Boolean = false,
    val publicUsername: String? = null,
    val linkedDiscussionChatId: String? = null,
    val channelSignaturesEnabled: Boolean = false
)

data class RealtimeOutgoingCallDto(
    val callId: String,
    val chatId: String,
    val peer: RealtimeUserSummaryDto,
    val mediaType: Int
)

data class RealtimeIncomingCallDto(
    val callId: String,
    val chatId: String,
    val caller: RealtimeUserSummaryDto,
    val mediaType: Int
)

data class RealtimeCallConnectedDto(
    val callId: String,
    val chatId: String,
    val connectedAt: String,
    val mediaType: Int,
    val iceServers: List<RealtimeCallIceServerDto> = emptyList(),
    val shouldCreateOffer: Boolean = false
)

data class RealtimeCallEndedDto(
    val callId: String,
    val chatId: String,
    val reason: String,
    val mediaType: Int
)

data class RealtimeCallIceServerDto(
    val urls: List<String>,
    val username: String? = null,
    val credential: String? = null
)

data class RealtimeCallOfferDto(
    val callId: String,
    val type: String,
    val sdp: String
)

data class RealtimeCallAnswerDto(
    val callId: String,
    val type: String,
    val sdp: String
)

data class RealtimeCallIceCandidateDto(
    val callId: String,
    val candidate: String,
    val sdpMid: String? = null,
    val sdpMLineIndex: Int
)

fun RealtimeUserSummaryDto.toCore(): UserSummaryDto = UserSummaryDto(
    id = id,
    username = username,
    displayName = displayName,
    isOnline = isOnline,
    phoneNumber = phoneNumber,
    lastSeenAt = lastSeenAt,
    about = about,
    avatarPath = avatarPath,
    isBot = isBot
)

fun RealtimeAttachmentDto.toCore(): AttachmentDto = AttachmentDto(
    id = id,
    fileName = fileName,
    contentType = contentType,
    fileSizeBytes = fileSizeBytes,
    downloadPath = downloadPath,
    kind = AttachmentKind.fromWireValue(kind),
    sortOrder = sortOrder
)

fun RealtimeMessageDto.toCore(): MessageDto = MessageDto(
    id = id,
    chatId = chatId,
    chatType = ChatType.fromWireValue(chatType),
    sender = sender.toCore(),
    text = text,
    attachments = attachments.map { it.toCore() },
    sentAt = sentAt,
    editedAt = editedAt,
    deletedAt = deletedAt,
    deliveryState = MessageDeliveryState.fromWireValue(deliveryState),
    forwardedFromDisplayName = forwardedFromDisplayName,
    replyTo = replyTo?.toCore(),
    pinnedAt = pinnedAt,
    pinnedBy = pinnedBy?.toCore(),
    mediaAlbumId = mediaAlbumId,
    reactions = reactions.map { it.toCore() },
    hasProtectedContent = hasProtectedContent,
    expiresAt = expiresAt,
    ttlSeconds = ttlSeconds,
    postedAsChannel = postedAsChannel,
    displayAuthorName = displayAuthorName,
    viewCount = viewCount
)

fun RealtimeMessageReplyDto.toCore(): MessageReplyDto = MessageReplyDto(
    messageId = messageId,
    senderId = senderId,
    senderDisplayName = senderDisplayName,
    previewText = previewText
)

fun RealtimeMessageReactionDto.toCore(): MessageReactionDto = MessageReactionDto(
    emoji = emoji,
    count = count,
    isMine = isMine
)

fun RealtimeChatSummaryDto.toCore(): ChatSummaryDto = ChatSummaryDto(
    id = id,
    title = title,
    type = ChatType.fromWireValue(type),
    secondaryText = secondaryText,
    lastActivityAt = lastActivityAt,
    lastMessagePreview = lastMessagePreview,
    participants = participants.map { it.toCore() },
    canSendMessages = canSendMessages,
    unreadCount = unreadCount,
    isPinned = isPinned,
    isArchived = isArchived,
    isMuted = isMuted,
    folderKey = folderKey,
    hasProtectedContent = hasProtectedContent,
    defaultMessageTtlSeconds = defaultMessageTtlSeconds,
    lastMessageAttachment = lastMessageAttachment?.toCore(),
    subscriberCount = subscriberCount,
    adminCount = adminCount,
    isSubscribed = isSubscribed,
    canSubscribe = canSubscribe,
    canManageChannel = canManageChannel,
    canPostAsChannel = canPostAsChannel,
    publicUsername = publicUsername,
    linkedDiscussionChatId = linkedDiscussionChatId,
    channelSignaturesEnabled = channelSignaturesEnabled
)

fun RealtimeOutgoingCallDto.toCore(): OutgoingCallDto = OutgoingCallDto(
    callId = callId,
    chatId = chatId,
    peer = peer.toCore(),
    mediaType = CallMediaType.fromWireValue(mediaType)
)

fun RealtimeIncomingCallDto.toCore(): IncomingCallDto = IncomingCallDto(
    callId = callId,
    chatId = chatId,
    caller = caller.toCore(),
    mediaType = CallMediaType.fromWireValue(mediaType)
)

fun RealtimeCallConnectedDto.toCore(): CallConnectedDto = CallConnectedDto(
    callId = callId,
    chatId = chatId,
    connectedAt = connectedAt,
    mediaType = CallMediaType.fromWireValue(mediaType),
    iceServers = iceServers.map { it.toCore() },
    shouldCreateOffer = shouldCreateOffer
)

fun RealtimeCallEndedDto.toCore(): CallEndedDto = CallEndedDto(
    callId = callId,
    chatId = chatId,
    reason = reason,
    mediaType = CallMediaType.fromWireValue(mediaType)
)

fun RealtimeCallIceServerDto.toCore(): CallIceServerDto = CallIceServerDto(
    urls = urls,
    username = username,
    credential = credential
)

fun CallIceServerDto.toRealtime(): RealtimeCallIceServerDto = RealtimeCallIceServerDto(
    urls = urls,
    username = username,
    credential = credential
)

fun RealtimeCallOfferDto.toCore(): CallOfferDto = CallOfferDto(
    callId = callId,
    type = type,
    sdp = sdp
)

fun CallOfferDto.toRealtime(): RealtimeCallOfferDto = RealtimeCallOfferDto(
    callId = callId,
    type = type,
    sdp = sdp
)

fun RealtimeCallAnswerDto.toCore(): CallAnswerDto = CallAnswerDto(
    callId = callId,
    type = type,
    sdp = sdp
)

fun CallAnswerDto.toRealtime(): RealtimeCallAnswerDto = RealtimeCallAnswerDto(
    callId = callId,
    type = type,
    sdp = sdp
)

fun RealtimeCallIceCandidateDto.toCore(): CallIceCandidateDto = CallIceCandidateDto(
    callId = callId,
    candidate = candidate,
    sdpMid = sdpMid,
    sdpMLineIndex = sdpMLineIndex
)

fun CallIceCandidateDto.toRealtime(): RealtimeCallIceCandidateDto = RealtimeCallIceCandidateDto(
    callId = callId,
    candidate = candidate,
    sdpMid = sdpMid,
    sdpMLineIndex = sdpMLineIndex
)
