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

import com.ffii.core.support.AbstractBaseEntityService
import com.ffii.core.support.JdbcDao
import com.ffii.fpsms.modules.common.SecurityUtils
import com.ffii.fpsms.modules.stock.entity.*
import com.ffii.fpsms.modules.stock.enums.EscalationLogStatus
import com.ffii.fpsms.modules.stock.web.model.SaveEscalationLogRequest
import com.ffii.fpsms.modules.stock.web.model.SaveEscalationLogResponse
import com.ffii.fpsms.modules.user.service.UserService
import org.springframework.stereotype.Service
import kotlin.jvm.optionals.getOrNull

@Service
open class EscalationLogService(
    private val jdbcDao: JdbcDao,
    private val escalationLogRepository: EscalationLogRepository,
    private val userService: UserService,
//    private val stockInLineService: StockInLineService,
    private val stockOutLineService: StockOutLineService,
    private val stockInLineRepository: StockInLineRepository,
    private val stockOutLIneRepository: StockOutLIneRepository,
): AbstractBaseEntityService<EscalationLog, Long, EscalationLogRepository>(jdbcDao, escalationLogRepository) {
    open fun getAllLogs(): List<EscalationLog> {
        return escalationLogRepository.findAll()
    }

    open fun getLogsByStockInLines(stockInLineIds: List<Long>?): List<EscalationLogInfo> {
        val logs = stockInLineIds?.let { escalationLogRepository.findAllInfoByDeletedFalseAndStockInLineIdIn(it) } ?: listOf()
        return logs
    }

    open fun getLogsByStockInLine(stockInLineId: Long?): List<EscalationLogInfo> {
        val logs = stockInLineId?.let { getLogsByStockInLines(listOf(it)) } ?: listOf()
        return logs
    }

    open fun getLogsByUser(): List<EscalationLogInfo> {
        val user = SecurityUtils.getUser().orElseThrow()
        val logs = user.id?.let { escalationLogRepository.findAllInfoByDeletedFalseAndHandlerIdIs(it) } ?: listOf()
//        val pendingLogs = logs.filter { it.status == EscalationLogStatus.PENDING.value }
        return logs
    }

    open fun saveEscalationLog(request: SaveEscalationLogRequest): SaveEscalationLogResponse{
        val escalationLog = request.id?.let { escalationLogRepository.findById(it).getOrNull() } ?: EscalationLog()
        val handler = request.handlerId.let { userService.getUserById(it) }
        if (handler == null && escalationLog.handler == null) {
            throw NoSuchElementException("Person In Charge is null.");
        }

        val stockInLine = request.stockInLineId?.let { stockInLineRepository.findById(it).getOrNull() }
        val stockOutLine = request.stockOutLineId?.let { stockOutLIneRepository.findById(it).getOrNull() }
        if (stockInLine == null && stockOutLine == null) {
            throw NoSuchElementException("Both stock in line and stock out line are null.");
        }

        val status = request.status.let { status -> EscalationLogStatus.entries.find{ it.value == status} }

        escalationLog.apply {
            this.handler = handler
            type = request.type
            this.stockInLine = stockInLine
            this.stockOutLine = stockOutLine
            recordDate = request.recordDate
            this.status = status
            reason = request.reason
            qcTotalCount = request.qcTotalCount
            qcFailCount = request.qcFailCount
        }

        val response = escalationLogRepository.save(escalationLog).let {
            SaveEscalationLogResponse(
                id = it.id,
                stockInLineId = it.stockInLine?.id,
                stockOutLineId = it.stockOutLine?.id,
                handlerId = it.handler?.id,
                handlerName = it.handler?.name,
                handlerTitle = it.handler?.title,
                handlerDepartment = it.handler?.department,
                recordDate = it.recordDate,
                status = it.status?.value,
                reason = it.reason,
            )
        }

        return response
    }
}