package com.pixelized.desktop.lwa.repository.inventory

import com.pixelized.shared.lwa.model.inventory.Inventory
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map

class InventoryRepository(
    private val inventoryStore: InventoryStore,
) {
    suspend fun updateInventoryFlow(characterSheetId: String) {
        inventoryStore.updateInventoryFlow(characterSheetId = characterSheetId)
    }

    fun inventoryFlow(): StateFlow<Map<String, Inventory>> {
        return inventoryStore.inventories
    }

    fun inventory(
        characterSheetId: String,
    ): Inventory {
        return inventoryStore.inventories.value[characterSheetId]
            ?: Inventory.empty(characterSheetId)
    }

    fun inventoryFlow(
        characterSheetId: String,
    ): Flow<Inventory> {
        return inventoryStore.inventories
            .map { it[characterSheetId] ?: Inventory.empty(characterSheetId) }
    }

    fun equippedItemsFlow(
        characterSheetId: String,
    ): Flow<List<Inventory.Item>> {
        return inventoryStore.inventories
            .map { it[characterSheetId] ?: Inventory.empty(characterSheetId) }
            .map { inventory -> inventory.items.filter { item -> item.equipped } }
    }

    @Throws
    suspend fun updateInventory(
        inventory: Inventory,
        create: Boolean,
    ) {
        inventoryStore.putInventory(
            inventory = inventory,
            create = create,
        )
    }

    @Throws
    suspend fun updateInventoryPurse(
        characterSheetId: String,
        purse: Inventory.Purse,
    ) {
        inventoryStore.putInventoryPurse(
            characterSheetId = characterSheetId,
            purse = purse,
        )
    }

    @Throws
    suspend fun createInventoryItem(
        characterSheetId: String,
        itemId: String,
        count: Float,
    ): String {
        return inventoryStore.createInventoryItem(
            characterSheetId = characterSheetId,
            itemId = itemId,
            count = count,
        )
    }

    @Throws
    suspend fun changeInventoryItemCount(
        characterSheetId: String,
        inventoryId: String,
        count: Float,
    ) {
        inventoryStore.changeInventoryItemCount(
            characterSheetId = characterSheetId,
            inventoryId = inventoryId,
            count = count,
        )
    }

    @Throws
    suspend fun consumeInventoryItem(
        characterSheetId: String,
        inventoryId: String,
    ) {
        inventoryStore.consumeInventoryItem(
            characterSheetId = characterSheetId,
            inventoryId = inventoryId,
        )
    }

    @Throws
    suspend fun equipInventoryItem(
        characterSheetId: String,
        inventoryId: String,
    ) {
        val inventory = inventory(characterSheetId = characterSheetId)
        val inventoryItem = inventory.items.firstOrNull { it.inventoryId == inventoryId }

        inventoryStore.equipInventoryItem(
            characterSheetId = characterSheetId,
            inventoryId = inventoryId,
            equip = inventoryItem?.equipped?.not() ?: true,
        )
    }

    @Throws
    suspend fun deleteInventoryItem(
        characterSheetId: String,
        inventoryId: String,
    ) {
        inventoryStore.deleteInventoryItem(
            characterSheetId = characterSheetId,
            inventoryId = inventoryId,
        )
    }
}