package com.ffii.fpsms.modules.stock.service

import com.ffii.fpsms.modules.master.entity.ItemUomRespository
import com.ffii.fpsms.modules.master.entity.WarehouseRepository
import com.ffii.fpsms.modules.stock.entity.InventoryLotLine
import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository
import com.ffii.fpsms.modules.stock.entity.InventoryLotRepository
import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus
import com.ffii.fpsms.modules.stock.entity.projection.InventoryLotLineInfo
import com.ffii.fpsms.modules.stock.web.model.SaveInventoryLotLineRequest
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
import java.math.BigDecimal
import java.util.Optional
import kotlin.jvm.optionals.getOrNull

@Service
open class InventoryLotLineService(
    private val inventoryLotLineRepository: InventoryLotLineRepository,
    private val inventoryLotRepository: InventoryLotRepository,
    private val warehouseRepository: WarehouseRepository,
    private val itemUomRespository: ItemUomRespository
) {
    open fun findById(id: Long): Optional<InventoryLotLine> {
        return inventoryLotLineRepository.findById(id)
    }

    open fun allInventoryLotLinesByItemIdIn(itemIds: List<Long>): List<InventoryLotLineInfo> {
        return inventoryLotLineRepository.findInventoryLotLineInfoByInventoryLotItemIdIn(itemIds)
    }

    open fun saveInventoryLotLine(request: SaveInventoryLotLineRequest): InventoryLotLine {
        val inventoryLotLine =
            request.id?.let { inventoryLotLineRepository.findById(it).getOrNull() } ?: InventoryLotLine()
        val inventoryLot = request.inventoryLotId?.let { inventoryLotRepository.findById(it).getOrNull() }
        val warehouse = request.warehouseId?.let { warehouseRepository.findById(it).getOrNull() }
        val stockUom = request.stockUomId?.let { itemUomRespository.findById(it).getOrNull() }
        val remainingQty =
            (request.inQty ?: BigDecimal(0)) - (request.outQty ?: BigDecimal(0)) - (request.holdQty ?: BigDecimal(0))
        val status = request.status?.let { _status -> InventoryLotLineStatus.entries.find { it.value == _status } }
        val qtyStatus = when (remainingQty > BigDecimal(0)) {
            true -> InventoryLotLineStatus.AVAILABLE
            else -> InventoryLotLineStatus.UNAVAILABLE
        }

        inventoryLotLine.apply {
            this.inventoryLot = inventoryLot
            this.warehouse = warehouse
            inQty = request.inQty
            outQty = request.outQty
            holdQty = request.holdQty
            this.stockUom = stockUom
            this.status =
                when (status == InventoryLotLineStatus.AVAILABLE && qtyStatus == InventoryLotLineStatus.AVAILABLE) {
                    true -> InventoryLotLineStatus.AVAILABLE
                    else -> InventoryLotLineStatus.UNAVAILABLE
                }
            remarks = request.remarks
        }

        return inventoryLotLineRepository.save(inventoryLotLine)
    }
}