package com.github.nullptroma.wallenc.usecases

import com.github.nullptroma.wallenc.domain.interfaces.IStorage
import com.github.nullptroma.wallenc.domain.interfaces.IVault
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import java.util.UUID
import javax.inject.Inject
import javax.inject.Singleton

@OptIn(ExperimentalCoroutinesApi::class)
@Singleton
class ManageVaultUseCase @Inject constructor(
    private val manager: IVaultsManager,
) {

    /** Найти vault по идентификатору в текущем состоянии. */
    fun find(vaultUuid: UUID): IVault? =
        manager.vaults.value.firstOrNull { it.uuid == vaultUuid }

    /** Реактивно отдаёт сам vault, либо null если он отсутствует. */
    fun observe(vaultUuid: UUID): Flow<IVault?> =
        manager.vaults.map { list -> list.firstOrNull { it.uuid == vaultUuid } }

    /** Реактивно отдаёт storages указанного vault'а; пустой список, если vault не найден. */
    fun storagesOf(vaultUuid: UUID): Flow<List<IStorage>> =
        observe(vaultUuid).flatMapLatest { vault -> vault?.storages ?: flowOf(emptyList()) }

    /** Идёт листинг/пересканирование storages vault'а. */
    fun storagesScanInProgressOf(vaultUuid: UUID): Flow<Boolean> =
        observe(vaultUuid).flatMapLatest { vault -> vault?.storagesScanInProgress ?: flowOf(false) }

    /** Создать новое хранилище в указанном vault'е. */
    suspend fun createStorage(vaultUuid: UUID): IStorage {
        val vault = find(vaultUuid)
            ?: throw IllegalStateException("Vault $vaultUuid is not registered")
        return vault.createStorage()
    }

    /** Пересканировать storages vault'а (листинг на Диске и повторный init). */
    suspend fun rescanStorages(vaultUuid: UUID) {
        val vault = find(vaultUuid)
            ?: throw IllegalStateException("Vault $vaultUuid is not registered")
        vault.rescanStorages()
    }
}
