@file:Suppress("HardCodedStringLiteral")
package eu.gaudian.translator.utils

import eu.gaudian.translator.viewmodel.MessageAction
import eu.gaudian.translator.viewmodel.MessageDisplayType
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch

/**
 * A sealed class representing all possible actions that can be sent to the status system.
 */
sealed class StatusAction {
    data class ShowMessage(val text: String, val type: MessageDisplayType, val timeoutInSeconds: Int) : StatusAction()
    data class ShowPermanentMessage(val text: String, val type: MessageDisplayType) : StatusAction()
    object CancelPermanentMessage : StatusAction()
    data class PerformLoadingOperation(val block: suspend () -> Unit) : StatusAction()
    object CancelLoadingOperation : StatusAction()
    object HideMessageBar : StatusAction()
    object CancelAllMessages : StatusAction()

    data class ShowActionableMessage(val text: String, val type: MessageDisplayType, val action: MessageAction) : StatusAction()
}

/**
 * A singleton object that acts as a central event bus for status messages.
 * Any part of the app can trigger an action, and any StatusViewModel listening will receive it.
 */
object StatusMessageService {
    private val _actions = MutableSharedFlow<StatusAction>()
    val actions = _actions.asSharedFlow()
    private val scope = CoroutineScope(Dispatchers.Default)

    suspend fun trigger(action: StatusAction) {
        Log.d("StatusMessageService", "Received action: $action")
        _actions.emit(action)
    }

    fun triggerNonSuspend(action: StatusAction) {
        Log.d("StatusMessageService", "Received non-suspend action: $action")
        scope.launch {
            _actions.emit(action)
        }
    }

    @Suppress("unused")
    fun showSimpleMessage(text: String, type: MessageDisplayType = MessageDisplayType.INFO) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(text, type, 5))
        }
    }

    fun showErrorMessage(text: String, timeoutInSeconds: Int = 5) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(
                text, MessageDisplayType.ERROR,
                timeoutInSeconds = timeoutInSeconds
            )
            )
        }
    }

    fun showLoadingMessage(text: String, timeoutInSeconds: Int = 0) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(
                text, MessageDisplayType.LOADING,
                timeoutInSeconds = timeoutInSeconds
            ))
        }
    }

    fun showInfoMessage(text: String, timeoutInSeconds: Int = 3) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(
                text, MessageDisplayType.INFO,
                timeoutInSeconds = timeoutInSeconds
            ))
        }
    }

    fun showSuccessMessage(text: String, timeoutInSeconds: Int = 3) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(
                text, MessageDisplayType.SUCCESS,
                timeoutInSeconds = timeoutInSeconds
            ))
        }
    }

    fun showPermanentMessage(text: String, type: MessageDisplayType) {
        scope.launch {
            _actions.emit(StatusAction.ShowPermanentMessage(text, type))
        }
    }

    fun cancelPermanentMessage() {
        scope.launch {
            _actions.emit(StatusAction.CancelPermanentMessage)
        }
    }

    fun hideMessageBar() {
        scope.launch {
            _actions.emit(StatusAction.HideMessageBar)
        }
    }

    fun cancelAllMessages() {
        scope.launch {
            _actions.emit(StatusAction.CancelAllMessages)
        }
    }

    fun showActionableMessage(text: String, type: MessageDisplayType, action: MessageAction) {
        scope.launch {
            _actions.emit(StatusAction.ShowActionableMessage(text, type, action))
        }
    }
}