/*
 * Book's Story — free and open-source Material You eBook reader.
 * Copyright (C) 2024-2026 Acclorite
 * SPDX-License-Identifier: GPL-3.0-only
 */

package org.dueattendant149.bookshelf.data.repository

import android.util.Log
import org.dueattendant149.bookshelf.core.ui.UIText
import org.dueattendant149.bookshelf.data.remote.bookshelfapi.BookshelfApiClientFactory
import org.dueattendant149.bookshelf.data.remote.bookshelfapi.model.LibraryResponse
import org.dueattendant149.bookshelf.data.settings.ServerSettings
import org.dueattendant149.bookshelf.domain.model.library.Book
import org.dueattendant149.bookshelf.domain.model.remote.RemoteLibrary
import org.dueattendant149.bookshelf.domain.repository.RemoteLibraryRepository
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class RemoteLibraryRepositoryImpl
    @Inject
    constructor(
        private val clientFactory: BookshelfApiClientFactory,
        private val serverSettings: ServerSettings,
    ) : RemoteLibraryRepository {
        override suspend fun getLibraries(): Result<List<RemoteLibrary>> {
            return runCatching {
                val client = client() ?: return Result.success(emptyList())
                val response = client.getLibraries()
                if (!response.isSuccessful) {
                    return Result.failure(RuntimeException("Failed to fetch libraries: ${response.code()}"))
                }
                response.body().orEmpty().map { it.toDomain() }
            }.onFailure {
                Log.e("RemoteLibraryRepo", "getLibraries failed", it)
            }
        }

        override suspend fun getBooks(libraryId: String): Result<List<Book>> {
            return searchLibrary(libraryId, "")
        }

        override suspend fun searchLibrary(
            libraryId: String,
            query: String,
        ): Result<List<Book>> {
            return runCatching {
                val client = client() ?: return Result.success(emptyList())
                val response = client.searchLibrary(libraryId, query)
                if (!response.isSuccessful) {
                    return Result.failure(RuntimeException("Failed to search library: ${response.code()}"))
                }
                response.body().orEmpty().map { it.toBook() }
            }.onFailure {
                Log.e("RemoteLibraryRepo", "searchLibrary failed", it)
            }
        }

        private suspend fun client() = serverSettings.getBookshelfUrl()?.let { clientFactory.provideClient(it) }

        private fun LibraryResponse.toDomain() =
            RemoteLibrary(
                id = id,
                name = name,
                mediaType = mediaType,
                itemCount = itemCount,
            )

        private fun org.dueattendant149.bookshelf.data.remote.bookshelfapi.model.BookItemResponse.toBook() =
            Book(
                id = 0,
                title = title,
                author = UIText.StringValue(author),
                description = null,
                filePath = "",
                coverImage = null,
                scrollIndex = 0,
                scrollOffset = 0,
                progress = 0f,
                lastOpened = null,
                categories = emptyList(),
                remoteId = id,
                libraryId = libraryId,
                mediaType = mediaType,
                hasAudio = mediaType == "audiobook" || mediaType == "podcast",
                hasEbook = mediaType == "book",
                audioDuration = duration.toLong(),
                coverUrl = coverUrl,
                lastSyncedAt = System.currentTimeMillis(),
            )
    }
