package com.github.nullptroma.wallenc.domain.interfaces

import com.github.nullptroma.wallenc.domain.datatypes.DataPage
import com.github.nullptroma.wallenc.domain.datatypes.StorageSyncJournal
import com.github.nullptroma.wallenc.domain.datatypes.StorageSyncLock
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import java.io.InputStream
import java.io.OutputStream
import java.time.Instant

interface IStorageAccessor {
    val size: StateFlow<Long?>
    val numberOfFiles: StateFlow<Int?>
    val isAvailable: StateFlow<Boolean>
    val filesUpdates: SharedFlow<DataPage<IFile>>
    val dirsUpdates: SharedFlow<DataPage<IDirectory>>

    suspend fun getAllFiles(): List<IFile>
    suspend fun getFiles(path: String): List<IFile>
    /**
     * Получение списка файлов в директории
     * @param path Путь к директории
     * @return Поток файлов
     */
    fun getFilesFlow(path: String): Flow<DataPage<IFile>>

    suspend fun getAllDirs(): List<IDirectory>
    suspend fun getDirs(path: String): List<IDirectory>
    /**
     * Получение списка директорий в директории
     * @param path Путь к директории
     * @return Поток директорий
     */
    fun getDirsFlow(path: String): Flow<DataPage<IDirectory>>
    suspend fun getFileInfo(path: String): IFile
    suspend fun getDirInfo(path: String): IDirectory
    suspend fun setHidden(path: String, hidden: Boolean)
    suspend fun touchFile(path: String)
    suspend fun touchDir(path: String)
    suspend fun delete(path: String, recordSyncJournal: Boolean = true)
    suspend fun openWrite(path: String, recordSyncJournal: Boolean = true): OutputStream
    suspend fun openRead(path: String): InputStream
    suspend fun moveToTrash(path: String, recordSyncJournal: Boolean = true)

    /**
     * Системный sidecar-файл для логических нужд хранилища (мета, ключи и т.п.).
     * Конкретный accessor решает, где он физически живёт, но он не должен
     * попадать в выдачу [getFiles]/[getDirs]/[size]/[numberOfFiles].
     */
    suspend fun openReadSystemFile(name: String): InputStream
    suspend fun openWriteSystemFile(name: String): OutputStream

    suspend fun readSyncJournal(): StorageSyncJournal

    /** Сбрасывает отложенные записи журнала на носитель (перед sync и при закрытии storage). */
    suspend fun flushPendingSyncJournal() = Unit

    suspend fun putSyncJournalEntries(entries: StorageSyncJournal)

    suspend fun readSyncLock(): StorageSyncLock?
    suspend fun tryAcquireSyncLock(holderId: String, leaseUntil: Instant): Boolean
    suspend fun releaseSyncLock(holderId: String)

    /**
     * Сбрасывает lock синхронизации без проверки [holderId] (снятие «залипшей» блокировки).
     * Не использовать в обычном цикле синка — только для ручного вмешательства.
     */
    suspend fun forceClearSyncLock()
}