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

import com.ffii.core.support.AbstractBaseEntityService
import com.ffii.core.support.JdbcDao
import com.ffii.fpsms.modules.master.entity.ItemsRepository
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import com.ffii.fpsms.modules.stock.entity.*
import com.ffii.fpsms.modules.stock.web.model.SaveStockOutLineRequest
import com.ffii.fpsms.modules.stock.web.model.SaveStockOutRequest
import com.ffii.fpsms.modules.stock.web.model.StockOutLineStatus
import com.ffii.fpsms.modules.stock.web.model.StockOutStatus
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.io.IOException
import java.time.LocalDate
import java.time.LocalDateTime

@Service
open class StockOutLineService(
    private val jdbcDao: JdbcDao,
    private val stockOutRepository: StockOutRepository,
    private val stockOutLIneRepository: StockOutLIneRepository,
    private val itemRepository: ItemsRepository,
    private val inventoryRepository: InventoryRepository,
    ): AbstractBaseEntityService<StockOutLine, Long, StockOutLIneRepository>(jdbcDao, stockOutLIneRepository)  {
    @Throws(IOException::class)
    @Transactional
    open fun findAllByStockOutId(stockOutId: Long): List<StockOutLine> {
        return stockOutLIneRepository.findAllByStockOutIdAndDeletedFalse(stockOutId)
    }
    @Throws(IOException::class)
    @Transactional
    open fun deleteById(id: Long): String {
        val deleteStockOutline = stockOutLIneRepository.findById(id).orElseThrow().apply {
            deleted = true
        }
        val updateItem = stockOutLIneRepository.save(deleteStockOutline)
        val response = "mark deleted item: ${updateItem.id}"
        return response
    }
    @Throws(IOException::class)
    @Transactional
    open fun deleteByStockOutId(id: Long): String {
        val deleteStockOutline = stockOutLIneRepository.findAllByStockOutIdAndDeletedFalse(id).map {sol ->
            sol.apply {
                deleted = true
            }
        }
        val updateItemIds = stockOutLIneRepository.saveAllAndFlush(deleteStockOutline).map { it.id }
        val response = "mark deleted items: $updateItemIds"
        return response
    }

    @Throws(IOException::class)
    @Transactional
    /// only create??????
    open fun create(request: SaveStockOutLineRequest): MessageResponse {
        val stockOutLine = StockOutLine()
        val item = itemRepository.findById(request.itemId).orElseThrow()
        stockOutLine.apply {
            this.item = item
            qty = request.qty
            status = StockOutLineStatus.PENDING.status //create the base record = the original total sum of one item
        }
        val savedStockOutLine = stockOutLIneRepository.saveAndFlush(stockOutLine)
        return MessageResponse(
            id = savedStockOutLine.id,
            code = item.code,
            name = item.name,
            type = savedStockOutLine.status,
            message = "save success",
            errorPosition = null
        )
    }
    // stock out -> stock out line record : {qty = 100}
    // each pick create new stock out line {...sol, status = picked}
    // when confirm all picked and complete in web
    // update:
    // 1.stock out status
    // remove:
    // 1.stock out line : {qty = 100}
    @Throws(IOException::class)
    @Transactional
    open fun pick(request: SaveStockOutLineRequest): MessageResponse {
        val item = itemRepository.findById(request.itemId).orElseThrow()
        if (request.inventoryId === null) {
            return MessageResponse(
                id = request.id,
                code = null,
                name = item.name,
                type = null,
                message = "inventory is null or not exist",
                errorPosition = "inventoryId"
            )
        }
        val stockOutLine = StockOutLine()
        val _stockOut = stockOutRepository.findById(request.stockOutId).orElseThrow()
        val _inventory = inventoryRepository.findById(request.inventoryId).orElseThrow()
        val picker = request.pickerId
        stockOutLine.apply {
            this.item = item
            qty = request.qty
            stockOut = _stockOut
            inventory = _inventory
            status = "picked"
            pickTime = LocalDateTime.now()
            pickerId = picker
        }
        val savedOutLine = stockOutLIneRepository.saveAndFlush(stockOutLine)
        return MessageResponse(
            id = savedOutLine.id,
            code = null,
            name = null,
            type = savedOutLine.status,
            message = "item picked",
            errorPosition = null
        )
    }
}