package com.syaroful.agrilinkvocpro.presentation.screen.home

import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.android.play.core.splitinstall.SplitInstallException
import com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener
import com.google.android.play.core.splitinstall.model.SplitInstallErrorCode
import com.google.android.play.core.splitinstall.model.SplitInstallSessionStatus
import com.syaroful.agrilinkvocpro.core.utils.DownloadState
import com.syaroful.agrilinkvocpro.data.repository.DynamicModuleRepository
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

class DynamicModuleViewModel(
    private val dynamicModuleRepository: DynamicModuleRepository
) : ViewModel() {

    var currentModuleToDownload = mutableStateOf<String?>(null)
        private set

    private var onLaunchCallback: ((String) -> Unit)? = null


    private val _showProgressDialog = MutableStateFlow(false)
    val showProgressDialog: StateFlow<Boolean> = _showProgressDialog

    private val _progressMessage = MutableStateFlow("")
    val progressMessage: StateFlow<String> = _progressMessage

    private val _progressPercent = MutableStateFlow(0f)
    val progressPercent: StateFlow<Float> = _progressPercent

    fun setDialogVisibility(show: Boolean) {
        _showProgressDialog.value = show
    }

    private val _downloadState = MutableStateFlow<DownloadState>(DownloadState.Idle)
    private val downloadState: StateFlow<DownloadState> = _downloadState.asStateFlow()

    init {
        observeDownloadStatus()
    }

    private val listener = SplitInstallStateUpdatedListener { state ->
        if (state.sessionId() == dynamicModuleRepository.getSessionId()) {
            when (state.status()) {
                SplitInstallSessionStatus.DOWNLOADING -> {
                    val progress = if (state.totalBytesToDownload() > 0)
                        state.bytesDownloaded().toFloat() / state.totalBytesToDownload()
                    else 0f
                    _downloadState.value = DownloadState.DownloadingWithProgress(progress)
                }

                SplitInstallSessionStatus.DOWNLOADED -> {
                    _downloadState.value = DownloadState.Downloaded
                }

                SplitInstallSessionStatus.INSTALLED -> {
                    _downloadState.value = DownloadState.Installed
                }

                SplitInstallSessionStatus.FAILED -> {
                    _downloadState.value = DownloadState.Failed("Installation Failed")
                }

                SplitInstallSessionStatus.CANCELED -> {
                    _downloadState.value = DownloadState.Failed("Installation Canceled")
                }

                else -> {}
            }
        }
    }

    fun onFeatureClicked(moduleName: String, onLaunch: (String) -> Unit) {
        if (isModuleDownloaded(moduleName)) {
            startFeatureActivity(moduleName, onLaunch)
        } else {
            currentModuleToDownload.value = moduleName
        }
    }

    fun confirmDownload(onLaunch: (String) -> Unit) {
        currentModuleToDownload.value?.let {
            downloadDynamicModule(it, onLaunch)
        }
        currentModuleToDownload.value = null
    }

    private fun downloadDynamicModule(moduleName: String, onLaunch: (String) -> Unit) {
        onLaunchCallback = onLaunch
        _downloadState.value = DownloadState.Starting

        dynamicModuleRepository.startDownload(moduleName, listener)
            .addOnFailureListener { exception ->
                val errorCode = (exception as? SplitInstallException)?.errorCode ?: -1
                val errorMessage = when (errorCode) {
                    SplitInstallErrorCode.NETWORK_ERROR -> "No Internet Connection"
                    SplitInstallErrorCode.MODULE_UNAVAILABLE -> "Module Unavailable"
                    SplitInstallErrorCode.ACTIVE_SESSIONS_LIMIT_EXCEEDED -> "Active Session Limit Exceeded"
                    SplitInstallErrorCode.INSUFFICIENT_STORAGE -> "Insufficient Storage"
                    SplitInstallErrorCode.PLAY_STORE_NOT_FOUND -> "Play Store Not Found"
                    else -> "Unknown Error: $errorCode"
                }
                _downloadState.value = DownloadState.Failed(errorMessage)
            }

    }


    private fun isModuleDownloaded(moduleName: String): Boolean {
        return dynamicModuleRepository.isModuleDownloaded(moduleName)
    }

    private fun observeDownloadStatus() {
        viewModelScope.launch {
            downloadState.collect { status ->
                when (status) {
                    is DownloadState.Idle -> {
                        _progressMessage.value = ""
                        _progressPercent.value = 0f
                    }

                    is DownloadState.Starting -> {
                        _showProgressDialog.value = true
                        _progressMessage.value = "Starting download..."
                        _progressPercent.value = 0f
                    }

                    is DownloadState.Downloading -> {
                        _showProgressDialog.value = true
                        _progressMessage.value = "Downloading module..."
                    }

                    is DownloadState.Downloaded -> {
                       _progressMessage.value = "Download completed"
                        _showProgressDialog.value = true
                        _progressPercent.value = 1f
                    }

                    is DownloadState.Installed -> {
                        _progressMessage.value = "Install completed"
                        _progressPercent.value = 1f
                        delayAndDismissDialog()
                    }

                    is DownloadState.Failed -> {
                        _progressMessage.value = "Failed: ${status.message}"
                        _showProgressDialog.value = true
                        _progressPercent.value = 0f
                    }

                    is DownloadState.DownloadingWithProgress -> {
                        _showProgressDialog.value = true
                        _progressPercent.value = status.progress
                    }
                }
            }
        }
    }

    private fun delayAndDismissDialog() {
        viewModelScope.launch {
            delay(1500)
            _showProgressDialog.value = false
            currentModuleToDownload.value?.let {
                onLaunchCallback?.invoke(it)
            }
            currentModuleToDownload.value = null
        }
    }

    private fun startFeatureActivity(moduleName: String, onLaunch: (String) -> Unit) {
        val className = when (moduleName) {
            "control_feature" -> "com.syaroful.agrilinkvocpro.control_feature.ControlActuatorActivity"
            "growth_recipe_feature" -> "com.syaroful.agrilinkvocpro.growth_recipe_feature.GrowthRecipeActivity"
            "commodity_price_prediction_feature" -> "com.syaroful.agrilinkvocpro.commodity_price_prediction_feature.PricePredictionActivity"
            "plant_disease_detection_feature" -> "com.syaroful.agrilinkvocpro.plant_disease_detection_feature.PlantDiseaseDetectionActivity"
            else -> null
        }
        className?.let { onLaunch(it) }
    }

    override fun onCleared() {
        super.onCleared()
        dynamicModuleRepository.unregisterListener(listener)
    }
}