package com.github.nullptroma.wallenc.usecases.fakes

import com.github.nullptroma.wallenc.domain.datatypes.StorageEncryptionInfo
import com.github.nullptroma.wallenc.domain.datatypes.StorageMetaLoadState
import com.github.nullptroma.wallenc.domain.datatypes.StorageSyncJournalEntry
import com.github.nullptroma.wallenc.domain.datatypes.StorageSyncJournalMerge
import com.github.nullptroma.wallenc.domain.interfaces.IStorage
import com.github.nullptroma.wallenc.domain.interfaces.IStorageAccessor
import com.github.nullptroma.wallenc.domain.interfaces.IStorageMetaInfo
import com.github.nullptroma.wallenc.domain.tasks.TaskProgress
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOf
import java.time.Instant
import java.util.UUID

class FakeStorage(
    override val uuid: UUID = UUID.randomUUID(),
    private val accessorImpl: FakeStorageAccessor = FakeStorageAccessor(),
    private val meta: FakeMetaInfo = FakeMetaInfo(),
) : IStorage {
    override val isAvailable: StateFlow<Boolean> = MutableStateFlow(true)
    override val size: StateFlow<Long?> = MutableStateFlow(0L)
    override val numberOfFiles: StateFlow<Int?> = MutableStateFlow(0)
    override val isEmpty: Flow<Boolean?> = flowOf(true)
    override val metaInfo: StateFlow<IStorageMetaInfo> = MutableStateFlow(meta)
    override val metaLoadState: StateFlow<StorageMetaLoadState> =
        MutableStateFlow(StorageMetaLoadState.Ready)
    override val isVirtualStorage: Boolean = false
    override val accessor: IStorageAccessor = accessorImpl

    override suspend fun rename(newName: String) = Unit

    override suspend fun setEncInfo(encInfo: StorageEncryptionInfo?) = Unit

    override suspend fun clearAllContent(onProgress: suspend (TaskProgress) -> Unit) = Unit

    fun setDomainFile(path: String, value: String) {
        putFile(path, value.encodeToByteArray())
    }

    fun putFile(path: String, bytes: ByteArray) {
        accessorImpl.dataFiles[com.github.nullptroma.wallenc.domain.datatypes.StorageSyncPaths.normalize(path)] =
            bytes
    }

    fun fileBytes(path: String): ByteArray? =
        accessorImpl.dataFiles[com.github.nullptroma.wallenc.domain.datatypes.StorageSyncPaths.normalize(path)]

    fun addSyncJournalEntry(entry: StorageSyncJournalEntry) {
        accessorImpl.syncJournal = StorageSyncJournalMerge.merge(
            accessorImpl.syncJournal,
            mapOf(entry.path to entry),
        )
    }

    fun syncJournalEntries(): List<StorageSyncJournalEntry> = accessorImpl.syncJournal.values.toList()

    fun setAcquireLockResult(result: Boolean) {
        accessorImpl.acquireLockResult = result
    }
}

class FakeMetaInfo(
    override val encInfo: StorageEncryptionInfo? = null,
    override val name: String = "Fake",
    override val lastModified: Instant = Instant.now(),
) : IStorageMetaInfo
