@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.
 * Supports both legacy string-based messages and new ID-based messages for internationalization.
 */
sealed class StatusAction {
    // Legacy string-based actions (deprecated in favor of ID-based actions)
    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()

    // New ID-based actions for internationalization
    data class ShowMessageById(
        val messageId: StatusMessageId,
        val type: MessageDisplayType = messageId.defaultType,
        val timeoutInSeconds: Int = messageId.defaultTimeout
    ) : StatusAction()
    data class ShowPermanentMessageById(
        val messageId: StatusMessageId,
        val type: MessageDisplayType = messageId.defaultType
    ) : StatusAction()
    data class ShowActionableMessageById(
        val messageId: StatusMessageId,
        val type: MessageDisplayType = messageId.defaultType,
        val action: MessageAction = messageId.associatedAction ?: MessageAction.NAVIGATE_TO_API_KEYS
    ) : 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.
 *
 * NOTE: All message display requests should go through this service.
 */
object StatusMessageService {
    private val _actions = MutableSharedFlow<StatusAction>()
    val actions = _actions.asSharedFlow()
    private val scope = CoroutineScope(Dispatchers.Default)

    /**
     * Triggers a status action. This is the primary way to display messages.
     * Internally launches a coroutine, so this function is not suspend.
     */
    fun trigger(action: StatusAction) {
        Log.d("StatusMessageService", "Received action: $action")
        scope.launch {
            _actions.emit(action)
        }
    }

    /**
     * @deprecated Use trigger() instead.
     */
    @Deprecated("Use trigger() instead", ReplaceWith("trigger(action)"))
    fun triggerNonSuspend(action: StatusAction) {
        trigger(action)
    }

    /**
     * @deprecated Use showMessageById() instead for internationalization support.
     */
    @Deprecated("Use showMessageById() for internationalization support", ReplaceWith("showMessageById(messageId)"))
    fun showSimpleMessage(text: String, type: MessageDisplayType = MessageDisplayType.INFO) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(text, type, 5))
        }
    }

    /**
     * @deprecated Use showErrorById() instead for internationalization support.
     */
    @Deprecated("Use showErrorById() for internationalization support", ReplaceWith("showErrorById(messageId)"))
    fun showErrorMessage(text: String, timeoutInSeconds: Int = 5) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(
                text, MessageDisplayType.ERROR,
                timeoutInSeconds = timeoutInSeconds
            )
            )
        }
    }

    /**
     * @deprecated Use showLoadingById() instead for internationalization support.
     */
    @Deprecated("Use showLoadingById() for internationalization support", ReplaceWith("showLoadingById(messageId)"))
    fun showLoadingMessage(text: String, timeoutInSeconds: Int = 0) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(
                text, MessageDisplayType.LOADING,
                timeoutInSeconds = timeoutInSeconds
            ))
        }
    }

    /**
     * @deprecated Use showInfoById() instead for internationalization support.
     */
    @Deprecated("Use showInfoById() for internationalization support", ReplaceWith("showInfoById(messageId)"))
    fun showInfoMessage(text: String, timeoutInSeconds: Int = 3) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(
                text, MessageDisplayType.INFO,
                timeoutInSeconds = timeoutInSeconds
            ))
        }
    }

    /**
     * @deprecated Use showSuccessById() instead for internationalization support.
     */
    @Deprecated("Use showSuccessById() for internationalization support", ReplaceWith("showSuccessById(messageId)"))
    fun showSuccessMessage(text: String, timeoutInSeconds: Int = 3) {
        scope.launch {
            _actions.emit(StatusAction.ShowMessage(
                text, MessageDisplayType.SUCCESS,
                timeoutInSeconds = timeoutInSeconds
            ))
        }
    }

    /**
     * @deprecated Use showPermanentMessageById() instead for internationalization support.
     */
    @Deprecated("Use showPermanentMessageById() for internationalization support", ReplaceWith("showPermanentMessageById(messageId)"))
    fun showPermanentMessage(text: String, type: MessageDisplayType) {
        scope.launch {
            _actions.emit(StatusAction.ShowPermanentMessage(text, type))
        }
    }

    /**
     * @deprecated Use StatusAction.CancelPermanentMessage via trigger() if needed.
     */
    @Deprecated("Use StatusAction.CancelPermanentMessage via trigger() if needed")
    fun cancelPermanentMessage() {
        trigger(StatusAction.CancelPermanentMessage)
    }

    /**
     * @deprecated Use StatusAction.HideMessageBar via trigger() if needed.
     */
    @Deprecated("Use StatusAction.HideMessageBar via trigger() if needed")
    fun hideMessageBar() {
        trigger(StatusAction.HideMessageBar)
    }

    /**
     * @deprecated Use StatusAction.CancelAllMessages via trigger() if needed.
     */
    @Deprecated("Use StatusAction.CancelAllMessages via trigger() if needed")
    fun cancelAllMessages() {
        trigger(StatusAction.CancelAllMessages)
    }

    /**
     * @deprecated Use showActionableMessageById() instead for internationalization support.
     */
    @Deprecated("Use showActionableMessageById() for internationalization support", ReplaceWith("showActionableMessageById(messageId)"))
    fun showActionableMessage(text: String, type: MessageDisplayType, action: MessageAction) {
        scope.launch {
            _actions.emit(StatusAction.ShowActionableMessage(text, type, action))
        }
    }

    // === NEW ID-BASED METHODS (for internationalization) ===

    /**
     * Shows a message by its ID. The actual text is resolved by StatusViewModel using string resources.
     * @param messageId The StatusMessageId that maps to a string resource
     * @param type Optional override for the display type
     * @param timeoutInSeconds Optional override for the timeout
     */
    fun showMessageById(
        messageId: StatusMessageId,
        type: MessageDisplayType = messageId.defaultType,
        timeoutInSeconds: Int = messageId.defaultTimeout
    ) {
        trigger(StatusAction.ShowMessageById(messageId, type, timeoutInSeconds))
    }

    /**
     * Shows a permanent message (until dismissed) by its ID.
     */
    fun showPermanentMessageById(
        messageId: StatusMessageId,
        type: MessageDisplayType = messageId.defaultType
    ) {
        trigger(StatusAction.ShowPermanentMessageById(messageId, type))
    }

    /**
     * Shows an actionable message by its ID with an optional action.
     */
    fun showActionableMessageById(
        messageId: StatusMessageId,
        type: MessageDisplayType = messageId.defaultType,
        action: MessageAction = messageId.associatedAction ?: MessageAction.NAVIGATE_TO_API_KEYS
    ) {
        trigger(StatusAction.ShowActionableMessageById(messageId, type, action))
    }

    // Convenience methods for common message types

    fun showErrorById(messageId: StatusMessageId, timeoutInSeconds: Int = messageId.defaultTimeout) {
        showMessageById(messageId, MessageDisplayType.ERROR, timeoutInSeconds)
    }

    fun showSuccessById(messageId: StatusMessageId, timeoutInSeconds: Int = messageId.defaultTimeout) {
        showMessageById(messageId, MessageDisplayType.SUCCESS, timeoutInSeconds)
    }

    fun showInfoById(messageId: StatusMessageId, timeoutInSeconds: Int = messageId.defaultTimeout) {
        showMessageById(messageId, MessageDisplayType.INFO, timeoutInSeconds)
    }

    fun showLoadingById(messageId: StatusMessageId, timeoutInSeconds: Int = messageId.defaultTimeout) {
        showMessageById(messageId, MessageDisplayType.LOADING, timeoutInSeconds)
    }
}
