package com.omixlab.lckcontrol.ui.plans

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.omixlab.lckcontrol.data.repository.StreamPlanRepository
import com.omixlab.lckcontrol.shared.StreamPlan
import com.omixlab.lckcontrol.shared.StreamingConfig
import com.omixlab.lckcontrol.streaming.StreamingManager
import com.omixlab.lckcontrol.streaming.StreamingState
import com.omixlab.lckcontrol.streaming.StreamingStats
import com.omixlab.lckcontrol.util.GameInfoProvider
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class PlanDetailViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    private val streamPlanRepository: StreamPlanRepository,
    val streamingManager: StreamingManager,
    val gameInfoProvider: GameInfoProvider,
) : ViewModel() {

    private val planId: String = savedStateHandle["planId"] ?: ""

    val plan: StateFlow<StreamPlan?> = streamPlanRepository.observePlan(planId)
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null)

    init {
        // Sync fresh state from backend
        viewModelScope.launch {
            try { streamPlanRepository.syncPlans() } catch (_: Exception) {}
        }
    }

    val streamingState: StateFlow<StreamingState> = streamingManager.state
    val streamingStats: StateFlow<StreamingStats> = streamingManager.stats

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

    private val _error = MutableStateFlow<String?>(null)
    val error: StateFlow<String?> = _error.asStateFlow()

    fun preparePlan() {
        viewModelScope.launch {
            _isLoading.value = true
            _error.value = null
            try {
                streamPlanRepository.preparePlan(planId)
            } catch (e: Exception) {
                _error.value = e.message ?: "Failed to prepare plan"
            } finally {
                _isLoading.value = false
            }
        }
    }

    fun startPlan() {
        viewModelScope.launch {
            _isLoading.value = true
            _error.value = null
            try {
                streamPlanRepository.startPlan(planId)
                // Start streaming engine for APP_STREAMING plans
                val updated = streamPlanRepository.getPlan(planId)
                if (updated?.executionMode == "APP_STREAMING") {
                    streamingManager.startStreaming(
                        plan = updated,
                        config = StreamingConfig(),
                        width = 1920,
                        height = 1080,
                    )
                }
            } catch (e: Exception) {
                _error.value = e.message ?: "Failed to start plan"
            } finally {
                _isLoading.value = false
            }
        }
    }

    fun endPlan() {
        viewModelScope.launch {
            _isLoading.value = true
            _error.value = null
            try {
                // Stop streaming engine if running
                if (streamingManager.isStreaming()) {
                    streamingManager.stopStreaming()
                }
                streamPlanRepository.endPlan(planId)
            } catch (e: Exception) {
                _error.value = e.message ?: "Failed to end plan"
            } finally {
                _isLoading.value = false
            }
        }
    }

    fun deletePlan(onDeleted: () -> Unit) {
        viewModelScope.launch {
            try {
                streamPlanRepository.deletePlan(planId)
                onDeleted()
            } catch (e: Exception) {
                _error.value = e.message ?: "Failed to delete plan"
            }
        }
    }

    fun clearError() {
        _error.value = null
    }
}
