package com.fabledsword.minstrel.admin.ui

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.fabledsword.minstrel.admin.data.AdminQuarantineRepository
import com.fabledsword.minstrel.api.ErrorCopy
import com.fabledsword.minstrel.connectivity.NetworkStatusController
import com.fabledsword.minstrel.connectivity.recoveries
import com.fabledsword.minstrel.events.EventsStream
import com.fabledsword.minstrel.models.AdminQuarantineItemRef
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import javax.inject.Inject

sealed interface AdminQuarantineUiState {
    data object Loading : AdminQuarantineUiState
    data object Empty : AdminQuarantineUiState
    data class Success(val rows: List<AdminQuarantineItemRef>) : AdminQuarantineUiState
    data class Error(val message: String) : AdminQuarantineUiState
}

@HiltViewModel
class AdminQuarantineViewModel @Inject constructor(
    private val repository: AdminQuarantineRepository,
    private val eventsStream: EventsStream,
    networkStatus: NetworkStatusController,
) : ViewModel() {

    private val internal = MutableStateFlow<AdminQuarantineUiState>(AdminQuarantineUiState.Loading)
    val uiState: StateFlow<AdminQuarantineUiState> = internal.asStateFlow()

    init {
        refresh()
        viewModelScope.launch {
            eventsStream.events
                .filter { it.kind.startsWith("quarantine.") }
                .collect { refresh() }
        }
        // Screen-level auto-recovery (issue #1245): reload a failed list
        // when server health returns instead of waiting for a manual pull.
        viewModelScope.launch {
            networkStatus.recoveries().collect {
                if (internal.value is AdminQuarantineUiState.Error) refresh()
            }
        }
    }

    fun refresh(): Job = viewModelScope.launch {
        internal.value = AdminQuarantineUiState.Loading
        try {
            val rows = repository.list()
            internal.value = if (rows.isEmpty()) {
                AdminQuarantineUiState.Empty
            } else {
                AdminQuarantineUiState.Success(rows)
            }
        } catch (
            @Suppress("TooGenericExceptionCaught") e: Throwable,
        ) {
            internal.value = AdminQuarantineUiState.Error(
                ErrorCopy.fromThrowable(e),
            )
        }
    }

    fun resolve(trackId: String) = act(trackId) { repository.resolve(it) }
    fun deleteFile(trackId: String) = act(trackId) { repository.deleteFile(it) }
    fun deleteViaLidarr(trackId: String) = act(trackId) { repository.deleteViaLidarr(it) }

    private fun act(trackId: String, action: suspend (String) -> Unit) {
        val before = internal.value
        if (before is AdminQuarantineUiState.Success) {
            val filtered = before.rows.filterNot { it.trackId == trackId }
            internal.value = if (filtered.isEmpty()) {
                AdminQuarantineUiState.Empty
            } else {
                AdminQuarantineUiState.Success(filtered)
            }
        }
        viewModelScope.launch {
            try {
                action(trackId)
            } catch (
                @Suppress("TooGenericExceptionCaught", "SwallowedException") e: Throwable,
            ) {
                refresh()
            }
        }
    }
}
