package ch.threema.app.messagedetails

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.ActionMode
import android.view.Menu
import android.view.MenuItem
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import ch.threema.android.buildActivityIntent
import ch.threema.app.AppConstants
import ch.threema.app.R
import ch.threema.app.activities.RecipientListBaseActivity
import ch.threema.app.activities.ThreemaToolbarActivity
import ch.threema.app.compose.common.spacer.SpacerVertical
import ch.threema.app.compose.common.text.HintText
import ch.threema.app.compose.edithistory.EditHistoryList
import ch.threema.app.compose.edithistory.EditHistoryViewModel
import ch.threema.app.compose.message.CompleteMessageBubble
import ch.threema.app.compose.message.MessageDebugInfoBox
import ch.threema.app.compose.message.MessageDetailsListBox
import ch.threema.app.compose.message.MessageTimestampsListBox
import ch.threema.app.compose.theme.ThreemaTheme
import ch.threema.app.compose.theme.dimens.GridUnit
import ch.threema.app.dialogs.BottomSheetGridDialog
import ch.threema.app.dialogs.GenericAlertDialog
import ch.threema.app.dialogs.GenericAlertDialog.DialogClickListener
import ch.threema.app.preference.service.PreferenceService
import ch.threema.app.ui.BottomSheetItem
import ch.threema.app.ui.CustomTextSelectionCallback
import ch.threema.app.utils.ConfigUtils
import ch.threema.app.utils.IntentDataUtil
import ch.threema.app.utils.LinkConfirmationListener.Companion.DIALOG_TAG_CONFIRM_LINK
import ch.threema.app.utils.LinkifyUtil
import ch.threema.app.utils.logScreenVisibility
import ch.threema.base.utils.getThreemaLogger
import ch.threema.storage.models.AbstractMessageModel
import ch.threema.storage.models.MessageType
import com.google.android.material.appbar.MaterialToolbar
import org.koin.android.ext.android.inject
import org.koin.androidx.compose.koinViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf

private val logger = getThreemaLogger("MessageDetailsActivity")

class MessageDetailsActivity : ThreemaToolbarActivity(), DialogClickListener, LinkifyUtil.LinkifyListener {
    init {
        logScreenVisibility(logger)
    }

    private val preferenceService: PreferenceService by inject()

    private lateinit var toolbar: MaterialToolbar

    private val viewModel: MessageDetailsViewModel by viewModel<MessageDetailsViewModel> {
        parametersOf(
            IntentDataUtil.getAbstractMessageId(intent),
            IntentDataUtil.getAbstractMessageType(intent),
        )
    }

    private val textSelectionCallback: CustomTextSelectionCallback =
        object : CustomTextSelectionCallback() {
            override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
                return true
            }

            override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
                menu.removeGroup(CONTEXT_MENU_GROUP)
                try {
                    if (textView != null) {
                        menu.add(
                            CONTEXT_MENU_GROUP,
                            CONTEXT_MENU_FORWARD,
                            200,
                            R.string.forward_text,
                        )
                    }
                } catch (e: Exception) {
                    // some MIUI devices crash when attempting to add a context menu
                    logger.error("Error adding context menu (Xiaomi?)", e)
                }
                return true
            }

            override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
                when (item.itemId) {
                    CONTEXT_MENU_FORWARD -> {
                        logger.info("Forward message clicked")
                        forwardText()
                    }

                    else -> return false
                }
                return true
            }

            override fun onDestroyActionMode(mode: ActionMode) {
                // we ignore this
            }

            private fun forwardText() {
                val textView = textView ?: return
                val text = textView.text

                if (text.isNotEmpty()) {
                    val start = textView.selectionStart
                    val end = textView.selectionEnd

                    val body = text.subSequence(start, end).toString()
                    val intent = Intent(
                        this@MessageDetailsActivity,
                        RecipientListBaseActivity::class.java,
                    )
                    intent.setType("text/plain")
                    intent.setAction(Intent.ACTION_SEND)
                    intent.putExtra(Intent.EXTRA_TEXT, body)
                    intent.putExtra(AppConstants.INTENT_DATA_IS_FORWARD, true)
                    startActivity(intent)
                }
            }
        }

    override fun getLayoutResource(): Int {
        return R.layout.activity_message_details
    }

    override fun initActivity(savedInstanceState: Bundle?): Boolean {
        theme.applyStyle(preferenceService.getFontStyle(), true)

        if (!super.initActivity(savedInstanceState)) {
            return false
        }

        initToolbar()
        initScreenContent()

        return true
    }

    override fun onLinkNeedsConfirmation(warning: String, uri: Uri) {
        val dialog = GenericAlertDialog.newInstance(R.string.url_warning_title, warning, R.string.ok, R.string.cancel)
        dialog.setData(uri)
        dialog.show(supportFragmentManager, DIALOG_TAG_CONFIRM_LINK)
    }

    override fun showBottomSheetGridDialog(items: ArrayList<BottomSheetItem?>?) {
        val dialog = BottomSheetGridDialog.newInstance(R.string.add_contact_in, items)
        dialog.setCallback { tag: String?, data: String? -> LinkifyUtil.launchAddContactActivity(this, tag, data) }
        dialog.show(supportFragmentManager, "bsh")
    }

    override fun shouldHandleLinkClick() = true

    private fun initScreenContent() {
        val editHistoryComposeView = findViewById<ComposeView>(R.id.message_details_compose_view)
        editHistoryComposeView.setViewCompositionStrategy(DisposeOnViewTreeLifecycleDestroyed)

        editHistoryComposeView.setContent {
            ThreemaTheme {
                val uiState: ChatMessageDetailsUiState by viewModel.uiState.collectAsStateWithLifecycle()
                val messageModel: MessageUiModel = uiState.message
                val editHistoryViewModel: EditHistoryViewModel = koinViewModel { parametersOf(messageModel.uid) }
                val editHistoryUiState by editHistoryViewModel.editHistoryUiState.collectAsStateWithLifecycle()

                Scaffold(
                    contentWindowInsets = WindowInsets.safeDrawing.only(
                        WindowInsetsSides.Horizontal + WindowInsetsSides.Bottom,
                    ),
                ) { insetsPadding ->

                    EditHistoryList(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(horizontal = GridUnit.x2),
                        contentPadding = insetsPadding,
                        editHistoryUiState = editHistoryUiState,
                        isOutbox = messageModel.isOutbox,
                        shouldMarkupText = uiState.shouldMarkupText,
                        linkifyListener = this,
                        headerContent = {
                            when (messageModel.type) {
                                MessageType.TEXT,
                                MessageType.FILE,
                                MessageType.LOCATION,
                                -> Column {
                                    SpacerVertical(height = GridUnit.x2)
                                    CompleteMessageBubble(
                                        message = messageModel,
                                        shouldMarkupText = uiState.shouldMarkupText,
                                        linkifyListener = this@MessageDetailsActivity,
                                        isTextSelectable = true,
                                        textSelectionCallback = textSelectionCallback,
                                    )
                                    if (uiState.hasReactions) {
                                        SpacerVertical(height = GridUnit.x0_25)
                                        HintText(
                                            text = stringResource(R.string.emoji_reactions_message_details_hint),
                                        )
                                    }
                                }

                                else -> Unit
                            }
                        },
                        footerContent = {
                            Column {
                                if (messageModel.messageTimestampsUiModel.hasProperties()) {
                                    SpacerVertical(height = GridUnit.x1)
                                    MessageTimestampsListBox(
                                        messageTimestampsUiModel = messageModel.messageTimestampsUiModel,
                                        isOutbox = messageModel.isOutbox,
                                    )
                                }
                                if (messageModel.messageDetailsUiModel.hasProperties()) {
                                    SpacerVertical(height = GridUnit.x2)
                                    MessageDetailsListBox(
                                        messageDetailsUiModel = messageModel.messageDetailsUiModel,
                                        isOutbox = messageModel.isOutbox,
                                    )
                                }
                                if (preferenceService.showMessageDebugInfo()) {
                                    SpacerVertical(height = GridUnit.x2)
                                    MessageDebugInfoBox(
                                        type = messageModel.type,
                                        rowId = messageModel.id,
                                        uid = messageModel.uid,
                                        isOutbox = messageModel.isOutbox,
                                    )
                                }
                            }
                        },
                    )
                }
            }
        }
    }

    private fun initToolbar() {
        toolbar = findViewById(R.id.material_toolbar)
        toolbar.setNavigationOnClickListener { finish() }
        toolbar.setOnMenuItemClickListener { item: MenuItem ->
            if (item.itemId == R.id.enable_formatting) {
                logger.info("Toggle formatting clicked")
                onToggleFormattingClicked(item)
                return@setOnMenuItemClickListener true
            }
            false
        }
        toolbar.setTitle(getString(R.string.message_log_title))
        ConfigUtils.addIconsToOverflowMenu(toolbar.getMenu())
    }

    private fun onToggleFormattingClicked(item: MenuItem) {
        item.setChecked(!item.isChecked)
        viewModel.markupText(item.isChecked)
    }

    override fun onYes(tag: String?, data: Any?) {
        if (DIALOG_TAG_CONFIRM_LINK == tag) {
            logger.info("Opening of link confirmed")
            LinkifyUtil.getInstance().openLink(data as Uri, this, this)
        }
    }

    companion object {
        private const val CONTEXT_MENU_FORWARD = 600
        private const val CONTEXT_MENU_GROUP = 22200

        @JvmStatic
        fun createIntent(context: Context, messageModel: AbstractMessageModel) = buildActivityIntent<MessageDetailsActivity>(context) {
            IntentDataUtil.append(messageModel, this)
        }
    }
}
