package com.ffii.fpsms.modules.jobOrder.service

import com.ffii.fpsms.modules.jobOrder.entity.JobOrderBomMaterial
import com.ffii.fpsms.modules.jobOrder.entity.JobOrderBomMaterialRepository
import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository
import com.ffii.fpsms.modules.jobOrder.enums.JobOrderBomMaterialStatus
import com.ffii.fpsms.modules.jobOrder.web.model.CreateJobOrderBomMaterialRequest
import com.ffii.fpsms.modules.master.entity.ItemsRepository
import com.ffii.fpsms.modules.master.entity.UomConversionRepository
import com.ffii.fpsms.modules.master.service.ItemUomService
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import org.springframework.stereotype.Service
import java.math.BigDecimal
import java.math.RoundingMode
import kotlin.jvm.optionals.getOrNull

@Service
open class JobOrderBomMaterialService(
    val jobOrderBomMaterialRepository: JobOrderBomMaterialRepository,
    private val jobOrderRepository: JobOrderRepository,
    private val itemsRepository: ItemsRepository,
    val itemUomService: ItemUomService,
    private val uomConversionRepository: UomConversionRepository
) {
    open fun createJobOrderBomMaterialRequests(joId: Long): List<CreateJobOrderBomMaterialRequest> {
        val zero = BigDecimal.ZERO
        val jo = jobOrderRepository.findById(joId).getOrNull() ?: throw NoSuchElementException()
        val proportion = (jo.reqQty ?: zero).divide(jo.bom?.outputQty ?: BigDecimal.ONE, 5, RoundingMode.HALF_UP)

        val jobmRequests = jo.bom?.bomMaterials?.map { bm ->
           // val salesUnit = bm.item?.id?.let { itemUomService.findSalesUnitByItemId(it) }
            val stockUnit = bm.item?.id?.let { itemUomService.findStockUnitByItemId(it) }
            CreateJobOrderBomMaterialRequest(
                joId = joId,
                itemId = bm.item?.id,
                //reqQty = (bm.qty?.times(proportion) ?: zero).setScale(0,RoundingMode.CEILING),
                reqQty = (bm.stockQty?.times(proportion) ?: zero).setScale(0, RoundingMode.CEILING),
                uomId = stockUnit?.uom?.id
            )
    } ?: listOf()

        return jobmRequests
    }

    fun createJobOrderBomMaterials(request: List<CreateJobOrderBomMaterialRequest>): MessageResponse {
        val joBomMaterials = request.map { req ->
            val jo = req.joId?.let { jobOrderRepository.findById(it).getOrNull() }
            val item = req.itemId?.let { itemsRepository.findById(it).getOrNull() }
            val uom = req.uomId?.let { uomConversionRepository.findById(it).getOrNull() }
            val roundedReqQty = req.reqQty?.setScale(0, RoundingMode.CEILING)
            val statusEnum = JobOrderBomMaterialStatus.entries.find { it.value == req.status }
                ?: JobOrderBomMaterialStatus.PENDING

            JobOrderBomMaterial().apply {
                jobOrder = jo
                this.item = item
                reqQty = roundedReqQty
                this.uom = uom
                this.status = statusEnum
            }
        }

        jobOrderBomMaterialRepository.saveAll(joBomMaterials)

        return MessageResponse(
            id = null,
            name = null,
            code = null,
            type = null,
            message = "Success",
            errorPosition = null
        )
    }

    fun createJobOrderBomMaterialsByJoId(joId: Long): MessageResponse {
        return createJobOrderBomMaterials(createJobOrderBomMaterialRequests(joId))
    }

    // After Picked Job Order Bom Material
    fun completeJobOrderBomMaterials(joId: Long): MessageResponse {
        val jobms = jobOrderBomMaterialRepository.findAllByJobOrderId(joId)
        val updatedJobms = jobms.map {
            it.apply {
                status = JobOrderBomMaterialStatus.COMPLETED
            }
        }

        jobOrderBomMaterialRepository.saveAll(updatedJobms)

        return MessageResponse(
            id = null,
            name = null,
            code = null,
            type = null,
            message = "Success",
            errorPosition = null
        )
    }

    fun completeJobOrderBomMaterialsByJoId(joId: Long): MessageResponse {
        return completeJobOrderBomMaterials(joId)
    }
}