package lu.rewardflow.terminal.data.repository

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import kotlinx.coroutines.flow.first
import lu.rewardflow.terminal.data.api.LoyaltyApi
import lu.rewardflow.terminal.data.model.CategoryItem
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Cached transaction categories for the store the device is paired to.
 *
 * The terminal action sheets (add stamp / earn points) show category pills
 * that the staff member multi-selects. Categories rarely change, so the
 * tablet caches the list and refreshes opportunistically (on app launch
 * and after any successful network round-trip).
 */
@Singleton
class CategoryRepository @Inject constructor(
    private val api: LoyaltyApi,
    private val configRepository: DeviceConfigRepository,
    moshi: Moshi,
) {

    private val listAdapter: JsonAdapter<List<CategoryItem>> = moshi.adapter(
        Types.newParameterizedType(List::class.java, CategoryItem::class.java)
    )

    suspend fun refresh(): List<CategoryItem> {
        val response = api.listCategories()
        val categories = response.categories.filter { it.is_active }
        configRepository.saveCategories(listAdapter.toJson(categories))
        return categories
    }

    suspend fun cached(): List<CategoryItem> {
        val raw = configRepository.categoriesJson.first() ?: return emptyList()
        return runCatching { listAdapter.fromJson(raw) ?: emptyList() }
            .getOrDefault(emptyList())
    }

    suspend fun listOrRefresh(): List<CategoryItem> {
        val cached = cached()
        return cached.ifEmpty { refresh() }
    }

    /** Pick the right display label for a category given the staff member's
     *  language preference, falling back to the canonical `name`. */
    fun localizedName(category: CategoryItem, languageCode: String): String =
        category.name_translations?.get(languageCode) ?: category.name
}
