/*
 * 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.domain.use_case.history

import org.dueattendant149.bookshelf.core.log.logE
import org.dueattendant149.bookshelf.core.log.logI
import org.dueattendant149.bookshelf.domain.model.history.History
import org.dueattendant149.bookshelf.domain.repository.HistoryRepository
import org.dueattendant149.bookshelf.presentation.history.model.GroupedHistory
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import javax.inject.Inject

private const val TAG = "GetHistory"

class GetHistoryUseCase @Inject constructor(
    private val historyRepository: HistoryRepository
) {

    suspend operator fun invoke(query: String): List<GroupedHistory> {
        logI(TAG, "Getting all history.")

        fun getDayLabel(timeMillis: Long): String {
            val historyDate = Instant.ofEpochMilli(timeMillis)
                .atZone(ZoneId.systemDefault()).toLocalDate()
            val today = LocalDate.now()
            val yesterday = today.minusDays(1)

            return when (historyDate) {
                today -> "today"
                yesterday -> "yesterday"
                else -> historyDate.format(DateTimeFormatter.ofPattern("dd.MM.yy"))
            }
        }

        fun filterMaxElementsById(elements: List<History>): List<History> {
            val groupedById = elements.groupBy { it.book.id }
            val maxElementsById = groupedById.map { (_, values) ->
                values.maxByOrNull { it.time }
            }
            return maxElementsById.filterNotNull()
        }

        val query = query.lowercase().trim()
        return runCatching {
            historyRepository.getHistory().getOrThrow()
                .filter { history -> history.book.title.lowercase().trim().contains(query) }
                .sortedByDescending { history -> history.time }
                .groupBy { history -> getDayLabel(history.time) }
                .map { (day, history) -> GroupedHistory(day, filterMaxElementsById(history)) }
        }.fold(
            onSuccess = {
                logI(TAG, "Successfully got ${it.size} grouped history entries.")
                it
            },
            onFailure = {
                logE(TAG, "Could not get grouped history entries with error: ${it.message}")
                emptyList()
            }
        )
    }
}