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

import androidx.lifecycle.SavedStateHandle
import com.github.nullptroma.wallenc.domain.interfaces.ILogger
import com.github.nullptroma.wallenc.domain.interfaces.IVault
import com.github.nullptroma.wallenc.domain.tasks.ITaskOrchestrator
import com.github.nullptroma.wallenc.ui.R
import com.github.nullptroma.wallenc.ui.resources.UiStringResolver
import com.github.nullptroma.wallenc.vault.contract.CloudBrand
import com.github.nullptroma.wallenc.vault.contract.DescribedVault
import com.github.nullptroma.wallenc.vault.contract.VaultDescriptor
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 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 java.util.UUID
import javax.inject.Inject

@OptIn(ExperimentalCoroutinesApi::class)
@HiltViewModel
class RemoteVaultViewModel @Inject constructor(
    savedStateHandle: SavedStateHandle,
    manageVaultUseCase: ManageVaultUseCase,
    removeStorageUseCase: RemoveStorageUseCase,
    getOpenedStoragesUseCase: GetOpenedStoragesUseCase,
    storageFileManagementUseCase: StorageFileManagementUseCase,
    manageStoragesEncryptionUseCase: ManageStoragesEncryptionUseCase,
    renameStorageUseCase: RenameStorageUseCase,
    taskOrchestrator: ITaskOrchestrator,
    uiStrings: UiStringResolver,
    logger: ILogger,
) : AbstractVaultBrowserViewModel(
    storagesFlow = manageVaultUseCase.storagesOf(savedStateHandle.requireVaultUuid()),
    storagesScanInProgressFlow = manageVaultUseCase.storagesScanInProgressOf(
        savedStateHandle.requireVaultUuid(),
    ),
    vaultHeaderFlow = manageVaultUseCase.observe(savedStateHandle.requireVaultUuid())
        .map { vault -> vault.toRemoteVaultBrowserHeader() },
    vaultAvailabilityFlow = manageVaultUseCase.observe(savedStateHandle.requireVaultUuid())
        .flatMapLatest { v -> v?.isAvailable ?: flowOf(false) },
    resolveCreateVaultUuid = { savedStateHandle.requireVaultUuid() },
    removeStorageUseCase = removeStorageUseCase,
    getOpenedStoragesUseCase = getOpenedStoragesUseCase,
    storageFileManagementUseCase = storageFileManagementUseCase,
    manageStoragesEncryptionUseCase = manageStoragesEncryptionUseCase,
    renameStorageUseCase = renameStorageUseCase,
    manageVaultUseCase = manageVaultUseCase,
    taskOrchestrator = taskOrchestrator,
    uiStrings = uiStrings,
    logger = logger,
) {
    override val supportsStorageRescan: Boolean = true
}

private fun SavedStateHandle.requireVaultUuid(): UUID {
    val raw = get<String>("vaultUuid") ?: error("Missing vault UUID in navigation arguments")
    return UUID.fromString(raw)
}

private fun IVault?.toRemoteVaultBrowserHeader(): VaultBrowserHeader? {
    val remote = (this as? DescribedVault)?.descriptor as? VaultDescriptor.LinkedRemote ?: return null
    val subtitle = when (remote.brand) {
        CloudBrand.YANDEX -> remote.accountDisplayName
    }
    val titleResId = when (remote.brand) {
        CloudBrand.YANDEX -> R.string.screen_title_yandex_vault
    }
    return VaultBrowserHeader(
        titleResId = titleResId,
        subtitle = subtitle,
    )
}
