package com.github.nullptroma.wallenc.ui.screens.main.screens.vault

import com.github.nullptroma.wallenc.domain.interfaces.ILogger
import com.github.nullptroma.wallenc.domain.interfaces.IVault
import com.github.nullptroma.wallenc.domain.interfaces.IVaultsManager
import com.github.nullptroma.wallenc.ui.R
import com.github.nullptroma.wallenc.domain.tasks.ITaskOrchestrator
import com.github.nullptroma.wallenc.ui.resources.UiStringResolver
import com.github.nullptroma.wallenc.usecases.GetOpenedStoragesUseCase
import com.github.nullptroma.wallenc.usecases.ManageStoragesEncryptionUseCase
import com.github.nullptroma.wallenc.usecases.ManageVaultUseCase
import com.github.nullptroma.wallenc.usecases.RemoveStorageUseCase
import com.github.nullptroma.wallenc.usecases.RenameStorageUseCase
import com.github.nullptroma.wallenc.usecases.StorageFileManagementUseCase
import com.github.nullptroma.wallenc.vault.contract.DescribedVault
import com.github.nullptroma.wallenc.vault.contract.VaultDescriptor
import com.github.nullptroma.wallenc.vault.contract.described
import com.github.nullptroma.wallenc.vault.contract.locals
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import javax.inject.Inject

@OptIn(ExperimentalCoroutinesApi::class)
@HiltViewModel
class LocalVaultViewModel @Inject constructor(
    vaultsManager: IVaultsManager,
    manageVaultUseCase: ManageVaultUseCase,
    removeStorageUseCase: RemoveStorageUseCase,
    getOpenedStoragesUseCase: GetOpenedStoragesUseCase,
    storageFileManagementUseCase: StorageFileManagementUseCase,
    manageStoragesEncryptionUseCase: ManageStoragesEncryptionUseCase,
    renameStorageUseCase: RenameStorageUseCase,
    taskOrchestrator: ITaskOrchestrator,
    uiStrings: UiStringResolver,
    logger: ILogger,
) : AbstractVaultBrowserViewModel(
    storagesFlow = vaultsManager.vaults
        .map { vaults -> vaults.described().locals.firstOrNull() }
        .flatMapLatest { v -> v?.storages ?: flowOf(emptyList()) },
    vaultHeaderFlow = vaultsManager.vaults
        .map { vaults -> vaults.described().locals.firstOrNull().toLocalVaultBrowserHeader() },
    vaultAvailabilityFlow = vaultsManager.vaults
        .map { vaults -> vaults.described().locals.firstOrNull() }
        .flatMapLatest { v -> v?.isAvailable ?: flowOf(false) },
    resolveCreateVaultUuid = { vaultsManager.vaults.value.described().locals.firstOrNull()?.uuid },
    removeStorageUseCase = removeStorageUseCase,
    getOpenedStoragesUseCase = getOpenedStoragesUseCase,
    storageFileManagementUseCase = storageFileManagementUseCase,
    manageStoragesEncryptionUseCase = manageStoragesEncryptionUseCase,
    renameStorageUseCase = renameStorageUseCase,
    manageVaultUseCase = manageVaultUseCase,
    taskOrchestrator = taskOrchestrator,
    uiStrings = uiStrings,
    logger = logger,
)

private fun IVault?.toLocalVaultBrowserHeader(): VaultBrowserHeader? {
    if ((this as? DescribedVault)?.descriptor !is VaultDescriptor.LocalDevice) return null
    return VaultBrowserHeader(titleResId = R.string.screen_title_local_vault)
}
