package com.syaroful.agrilinkvocpro.control_feature.presentation.control

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.syaroful.agrilinkvocpro.control_feature.core.state.ControlState
import com.syaroful.agrilinkvocpro.control_feature.data.model.ActuatorStatusResponse
import com.syaroful.agrilinkvocpro.control_feature.data.model.ActuatorType
import com.syaroful.agrilinkvocpro.control_feature.data.repository.ControlRepository
import com.syaroful.agrilinkvocpro.data.UserPreferences
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch

private const val TAG = "ControlViewModel"

class ControlViewModel(
    private val userPreferences: UserPreferences,
    private val repository: ControlRepository
) : ViewModel() {
    private val _allActuatorState =
        MutableStateFlow<ControlState<ActuatorStatusResponse>>(ControlState.Idle)
    val allActuatorState: StateFlow<ControlState<ActuatorStatusResponse>> = _allActuatorState

    private val _waterValveStatus = MutableStateFlow<Boolean>(false)
    val waterValveStatus: StateFlow<Boolean> = _waterValveStatus

    private val _nutritionValveStatus = MutableStateFlow<Boolean>(false)
    val nutritionValveStatus: StateFlow<Boolean> = _nutritionValveStatus

    private val _pumpStatus = MutableStateFlow<Boolean>(false)
    val pumpStatus: StateFlow<Boolean> = _pumpStatus

    private val _isLoading = MutableStateFlow<Boolean>(false)
    val isLoading: StateFlow<Boolean> = _isLoading

    fun getActuatorStatus() {
        _allActuatorState.value = ControlState.Loading
        viewModelScope.launch {
            val token = userPreferences.tokenFlow.first()
            val authHeader = "Bearer $token"
            try {
                delay(500L)
                val response = repository.getActuatorStatus(authHeader)
                if (response.isSuccessful) {
                    val data = response.body()
                    _allActuatorState.value = ControlState.Success(data)
                    data?.data?.forEach { actuator ->
                        val isOn = actuator?.currentStatus == "ON"
                        when (actuator?.name) {
                            ActuatorType.WATER.displayName -> _waterValveStatus.value = isOn
                            ActuatorType.NUTRIENT.displayName -> _nutritionValveStatus.value = isOn
                            ActuatorType.PUMP.displayName -> _pumpStatus.value = isOn
                        }
                    }
                } else {
                    val errorBody = response.errorBody()?.string()
                    val errorMessage = errorBody ?: "Error ${response.code()}"
                    _allActuatorState.value = ControlState.Error(errorMessage)
                }
            } catch (e: Exception) {
                _allActuatorState.value = ControlState.Error(e.message ?: "Unknown error")
            }
        }
    }


    fun controlActuator(actuator: ActuatorType, state: Boolean) {
        _isLoading.value = true
        viewModelScope.launch {
            val token = userPreferences.tokenFlow.first()
            val authHeader = "Bearer $token"
            val stringState = if (state) "ON" else "OFF"
            try {
                delay(500L)

                val response = when (actuator) {
                    ActuatorType.WATER -> repository.controlWaterValve(authHeader, stringState)
                    ActuatorType.NUTRIENT -> repository.controlNutrientValve(authHeader, stringState)
                    ActuatorType.PUMP -> repository.controlPump(authHeader, stringState)
                }

                if (response.isSuccessful) {
                    val isOn = response.body()?.log?.action == "ON"
                    updateActuatorStatus(actuator, isOn)
                    Log.d(TAG, "Successfully controlled ${actuator.displayName}")
                } else {
                    val errorBody = response.errorBody()?.string()
                    Log.e(TAG, "Error controlling ${actuator.displayName}: $errorBody")
                }
            } catch (e: Exception) {
                Log.e(TAG, "Exception while controlling ${actuator.displayName}: ${e.message}")
            } finally {
                _isLoading.value = false
            }
        }
    }

    private fun updateActuatorStatus(actuator: ActuatorType, isOn: Boolean) {
        when (actuator) {
            ActuatorType.WATER -> _waterValveStatus.value = isOn
            ActuatorType.NUTRIENT -> _nutritionValveStatus.value = isOn
            ActuatorType.PUMP -> _pumpStatus.value = isOn
        }
    }

}