/*
 * Copyright (c) 2025 Element Creations Ltd.
 * Copyright 2023-2025 New Vector Ltd.
 *
 * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
 * Please see LICENSE files in the repository root for full details.
 */

package id.databisnis.android.bachot.features.messages.impl.timeline.factories.event

import dev.zacsweers.metro.Inject
import id.databisnis.android.bachot.features.messages.impl.timeline.model.event.TimelineItemEventContent
import id.databisnis.android.bachot.features.messages.impl.timeline.model.event.TimelineItemLegacyCallInviteContent
import id.databisnis.android.bachot.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import id.databisnis.android.bachot.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
import id.databisnis.android.bachot.libraries.matrix.api.core.EventId
import id.databisnis.android.bachot.libraries.matrix.api.core.SessionId
import id.databisnis.android.bachot.libraries.matrix.api.core.UserId
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.CallNotifyContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.EventContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.EventTimelineItem
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.LegacyCallInviteContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.MessageContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.PollContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.ProfileChangeContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.ProfileDetails
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.RedactedContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.RoomMembershipContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.StateContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.StickerContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.UnknownContent
import id.databisnis.android.bachot.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName

@Inject
class TimelineItemContentFactory(
    private val messageFactory: TimelineItemContentMessageFactory,
    private val redactedMessageFactory: TimelineItemContentRedactedFactory,
    private val stickerFactory: TimelineItemContentStickerFactory,
    private val pollFactory: TimelineItemContentPollFactory,
    private val utdFactory: TimelineItemContentUTDFactory,
    private val roomMembershipFactory: TimelineItemContentRoomMembershipFactory,
    private val profileChangeFactory: TimelineItemContentProfileChangeFactory,
    private val stateFactory: TimelineItemContentStateFactory,
    private val failedToParseMessageFactory: TimelineItemContentFailedToParseMessageFactory,
    private val failedToParseStateFactory: TimelineItemContentFailedToParseStateFactory,
    private val sessionId: SessionId,
) {
    suspend fun create(eventTimelineItem: EventTimelineItem): TimelineItemEventContent {
        return create(
            itemContent = eventTimelineItem.content,
            eventId = eventTimelineItem.eventId,
            isEditable = eventTimelineItem.isEditable,
            sender = eventTimelineItem.sender,
            senderProfile = eventTimelineItem.senderProfile,
        )
    }

    suspend fun create(
        itemContent: EventContent,
        eventId: EventId?,
        isEditable: Boolean,
        sender: UserId,
        senderProfile: ProfileDetails,
    ): TimelineItemEventContent {
        val isOutgoing = sessionId == sender
        return when (itemContent) {
            is FailedToParseMessageLikeContent -> failedToParseMessageFactory.create(itemContent)
            is FailedToParseStateContent -> failedToParseStateFactory.create(itemContent)
            is MessageContent -> {
                val senderDisambiguatedDisplayName = senderProfile.getDisambiguatedDisplayName(sender)
                messageFactory.create(
                    content = itemContent,
                    senderDisambiguatedDisplayName = senderDisambiguatedDisplayName,
                    eventId = eventId,
                )
            }
            is ProfileChangeContent -> {
                val senderDisambiguatedDisplayName = senderProfile.getDisambiguatedDisplayName(sender)
                profileChangeFactory.create(itemContent, isOutgoing, sender, senderDisambiguatedDisplayName)
            }
            is RedactedContent -> redactedMessageFactory.create(itemContent)
            is RoomMembershipContent -> {
                val senderDisambiguatedDisplayName = senderProfile.getDisambiguatedDisplayName(sender)
                roomMembershipFactory.create(itemContent, isOutgoing, sender, senderDisambiguatedDisplayName)
            }
            is LegacyCallInviteContent -> TimelineItemLegacyCallInviteContent
            is StateContent -> {
                val senderDisambiguatedDisplayName = senderProfile.getDisambiguatedDisplayName(sender)
                stateFactory.create(itemContent, isOutgoing, sender, senderDisambiguatedDisplayName)
            }
            is StickerContent -> stickerFactory.create(itemContent)
            is PollContent -> pollFactory.create(eventId, isEditable, isOutgoing, itemContent)
            is UnableToDecryptContent -> utdFactory.create(itemContent)
            is CallNotifyContent -> TimelineItemRtcNotificationContent()
            is UnknownContent -> TimelineItemUnknownContent
        }
    }
}
