package dev.fyloz.trial.colorrecipesexplorer.service

import dev.fyloz.trial.colorrecipesexplorer.exception.TooLowQuantityException
import dev.fyloz.trial.colorrecipesexplorer.model.InventoryMaterial
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.dto.InventoryDto
import dev.fyloz.trial.colorrecipesexplorer.model.toInventoryMaterial
import org.springframework.stereotype.Service

const val minimumQuantity = 100.0f  // TODO quantity stored in database

@Service
class InventoryService(val materialService: MaterialServiceImpl) {
    fun getAllMaterials(): Collection<InventoryMaterial> {
        return materialService.getAllNotMixType().map { it.toInventoryMaterial(minimumQuantity) }
    }

    /**
     * Use all materials in the given [mixes].
     * @throws TooLowQuantityException When there is not enough stock for a material
     */
    fun use(mixes: List<InventoryDto>) {
        mixes.forEach { mix ->
            val materials = mix.materialIds.toMaterials()

            materials.forEachIndexed { index, material ->
                val quantity = mix.quantities[index]

                if (!material.hasEnoughStock(quantity))
                    throw TooLowQuantityException(mix.mixId, material, material.inventoryQuantity, quantity)

                material.use(quantity)
            }
        }
    }

    /** Convert material ids to [Material]s. */
    private fun List<Long>.toMaterials(): List<Material> {
        return map { materialService.getById(it) }
    }

    /** Check if there is at least the given [quantity] in stock for a [Material]. */
    private fun Material.hasEnoughStock(quantity: Float): Boolean {
        return inventoryQuantity >= quantity
    }

    /** Use a given [Material], for the given [quantity]. */
    private fun Material.use(quantity: Float) {
        inventoryQuantity -= quantity
        materialService.update(this)
    }
}
