package net.sergeych.toread

import net.sergeych.toread.fb2.Fb2Book
import net.sergeych.toread.fb2.Fb2Format

internal sealed interface AppState {
    data object LoadingStartup : AppState
    data class Library(
        val items: List<LibraryItem>,
        val scanPath: String,
        val message: String? = null,
    ) : AppState

    data class Scan(
        val items: List<LibraryItem>,
        val scanPath: String,
        val message: String? = null,
    ) : AppState

    data class Reader(
        val fileId: String,
        val book: Fb2Book,
        val libraryItems: List<LibraryItem>,
        val scanPath: String,
        val message: String? = null,
    ) : AppState

    data class BookInfo(
        val fileId: String,
        val book: Fb2Book,
        val libraryItems: List<LibraryItem>,
        val scanPath: String,
        val message: String? = null,
    ) : AppState

    data class Error(val message: String) : AppState
}

internal suspend fun loadStartupState(): AppState {
    val scanPath = try {
        defaultLibraryScanPath().orEmpty()
    } catch (t: Throwable) {
        return AppState.Error(t.message ?: strings.couldNotOpenLibrary)
    }
    loadPlatformOpenBookRequest()?.let { request ->
        return runCatching {
            AppState.Reader(
                fileId = request.id,
                book = Fb2Format.parse(request.bytes, request.displayName),
                libraryItems = emptyList(),
                scanPath = scanPath,
            )
    }.getOrElse {
            AppState.Library(emptyList(), scanPath, it.message ?: strings.couldNotOpen(request.displayName))
        }
    }
    val activeFileId = loadActiveReadingFileId() ?: return AppState.Library(emptyList(), scanPath)
    val item = loadLibraryItem(activeFileId)
    if (item == null) {
        saveActiveReadingFileId(null)
        return AppState.Library(emptyList(), scanPath)
    }
    return runCatching {
        val bytes = openLibraryBook(activeFileId) ?: error(strings.bookFileNotAvailable)
        AppState.Reader(
            fileId = activeFileId,
            book = Fb2Format.parse(bytes, item.storageUri ?: item.title),
            libraryItems = emptyList(),
            scanPath = scanPath,
        )
    }.getOrElse {
        saveActiveReadingFileId(null)
        AppState.Library(emptyList(), scanPath, it.message ?: strings.couldNotReopenLastBook())
    }
}

internal suspend fun loadLibraryState(message: String? = null, scanPath: String? = null): AppState =
    runCatching {
        AppState.Library(
            items = emptyList(),
            scanPath = scanPath ?: defaultLibraryScanPath().orEmpty(),
            message = message,
        )
    }.getOrElse {
        AppState.Error(it.message ?: strings.couldNotOpenLibrary)
    }
