// FPSMS-backend/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt
package com.ffii.fpsms.modules.pickOrder.service

import com.ffii.fpsms.modules.master.web.models.MessageResponse
import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssue
import com.ffii.fpsms.modules.pickOrder.entity.PickExecutionIssueRepository
import com.ffii.fpsms.modules.stock.entity.StockOutLine
import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository
import com.ffii.fpsms.modules.stock.entity.InventoryLotLine
import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository
import com.ffii.fpsms.modules.stock.entity.InventoryRepository
import com.ffii.fpsms.modules.stock.web.model.PickExecutionIssueRequest
import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService
import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.transaction.annotation.Propagation
import java.math.BigDecimal
import java.time.LocalDate
import java.time.LocalDateTime

@Service
open class PickExecutionIssueService(
    private val pickExecutionIssueRepository: PickExecutionIssueRepository,
    private val stockOutLineRepository: StockOutLIneRepository,
    private val inventoryLotLineRepository: InventoryLotLineRepository,
    private val inventoryRepository: InventoryRepository,
    private val suggestedPickLotService: SuggestedPickLotService
) {

    @Transactional(rollbackFor = [Exception::class])
    open fun recordPickExecutionIssue(request: PickExecutionIssueRequest): MessageResponse {
        try {
            // 1. 检查是否已经存在相同的 pick execution issue 记录
            val existingIssues = pickExecutionIssueRepository.findByPickOrderLineIdAndLotIdAndDeletedFalse(
                request.pickOrderLineId, 
                request.lotId ?: 0L
            )
            
            if (existingIssues.isNotEmpty()) {
                return MessageResponse(
                    id = null,
                    name = "Pick execution issue already exists",
                    code = "DUPLICATE",
                    type = "pick_execution_issue",
                    message = "A pick execution issue for this lot has already been recorded",
                    errorPosition = null
                )
            }

            // 2. 创建 pick execution issue 记录
            val pickExecutionIssue = PickExecutionIssue(
                pickOrderId = request.pickOrderId,
                pickOrderCode = request.pickOrderCode,
                pickOrderCreateDate = request.pickOrderCreateDate,
                pickExecutionDate = request.pickExecutionDate ?: LocalDate.now(),
                pickOrderLineId = request.pickOrderLineId,
                itemId = request.itemId,
                itemCode = request.itemCode,
                itemDescription = request.itemDescription,
                lotId = request.lotId,
                lotNo = request.lotNo,
                storeLocation = request.storeLocation,
                requiredQty = request.requiredQty,
                actualPickQty = request.actualPickQty,
                missQty = request.missQty,
                badItemQty = request.badItemQty,
                issueRemark = request.issueRemark,
                pickerName = request.pickerName,
                handledBy = request.handledBy,
                created = LocalDateTime.now(),
                createdBy = "system",
                modified = LocalDateTime.now(),
                modifiedBy = "system"
            )

            val savedIssue = pickExecutionIssueRepository.save(pickExecutionIssue)

            // 3. 获取相关数据
            val actualPickQty = request.actualPickQty ?: BigDecimal.ZERO
            val missQty = request.missQty ?: BigDecimal.ZERO
            val badItemQty = request.badItemQty ?: BigDecimal.ZERO
            val lotId = request.lotId
            val itemId = request.itemId

            println("=== PICK EXECUTION ISSUE PROCESSING (NEW LOGIC) ===")
            println("Actual Pick Qty: ${actualPickQty}")
            println("Miss Qty: ${missQty}")
            println("Bad Item Qty: ${badItemQty}")
            println("Lot ID: ${lotId}")
            println("Item ID: ${itemId}")
            println("================================================")

            // 4. 新的统一处理逻辑
            when {
                // 情况1: 只有 miss item (actualPickQty = 0, missQty > 0, badItemQty = 0)
                actualPickQty == BigDecimal.ZERO && missQty > BigDecimal.ZERO && badItemQty == BigDecimal.ZERO -> {
                    handleMissItemOnly(request, missQty)
                }
                
                // 情况2: 只有 bad item (badItemQty > 0, missQty = 0)
                badItemQty > BigDecimal.ZERO && missQty == BigDecimal.ZERO -> {
                    handleBadItemOnly(request, badItemQty)
                }
                
                // 情况3: 既有 miss item 又有 bad item
                missQty > BigDecimal.ZERO && badItemQty > BigDecimal.ZERO -> {
                    handleBothMissAndBadItem(request, missQty, badItemQty)
                }
                
                // ✅ 修复：情况4: 有 miss item 的情况（无论 actualPickQty 是多少）
                missQty > BigDecimal.ZERO -> {
                    handleMissItemWithPartialPick(request, actualPickQty, missQty)
                }
                
                // 情况5: 正常拣货 (actualPickQty > 0, 没有 miss 或 bad item)
                actualPickQty > BigDecimal.ZERO -> {
                    handleNormalPick(request, actualPickQty)
                }
                
                else -> {
                    println("Unknown case: actualPickQty=${actualPickQty}, missQty=${missQty}, badItemQty=${badItemQty}")
                }
            }


            return MessageResponse(
                id = savedIssue.id,
                name = "Pick execution issue recorded successfully",
                code = "SUCCESS",
                type = "pick_execution_issue",
                message = "Pick execution issue recorded successfully",
                errorPosition = null
            )

        } catch (e: Exception) {
            println("=== ERROR IN recordPickExecutionIssue ===")
            e.printStackTrace()
            return MessageResponse(
                id = null,
                name = "Failed to record pick execution issue",
                code = "ERROR",
                type = "pick_execution_issue",
                message = "Error: ${e.message}",
                errorPosition = null
            )
        }
    }
// FPSMS-backend/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt
// ✅ 修复：处理有部分拣货但有 miss item 的情况
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class])
private fun handleMissItemWithPartialPick(request: PickExecutionIssueRequest, actualPickQty: BigDecimal, missQty: BigDecimal) {
    println("=== HANDLING MISS ITEM WITH PARTIAL PICK (FIXED LOGIC) ===")
    println("Actual Pick Qty: ${actualPickQty}")
    println("Miss Qty: ${missQty}")
    
    val lotId = request.lotId ?: return
    val itemId = request.itemId ?: return
    val inventoryLotLine = inventoryLotLineRepository.findById(lotId).orElse(null)
    
    if (inventoryLotLine != null) {
        // ✅ 修复1：只处理已拣货的部分：更新 outQty
        val currentOutQty = inventoryLotLine.outQty ?: BigDecimal.ZERO
        val newOutQty = currentOutQty.add(actualPickQty)
        inventoryLotLine.outQty = newOutQty
        
        // ✅ 修复2：Miss item 不减少 inQty，而是标记为 unavailable
        // 因为 miss item 意味着这些物品实际上不存在或找不到
        // 所以应该标记整个批次为 unavailable，而不是减少 inQty
        
        // ✅ 修复3：如果 missQty > 0，标记批次为 unavailable
        if (missQty > BigDecimal.ZERO) {
            inventoryLotLine.status = InventoryLotLineStatus.UNAVAILABLE
        }
        
        inventoryLotLine.modified = LocalDateTime.now()
        inventoryLotLine.modifiedBy = "system"
        inventoryLotLineRepository.save(inventoryLotLine)
        
        println("Miss item with partial pick: Updated lot ${lotId}")
        println("  - Added to outQty: ${actualPickQty} (${currentOutQty} -> ${newOutQty})")
        println("  - Set status to UNAVAILABLE due to missQty: ${missQty}")
    }
    
    // ✅ 修复4：更新 inventory 表的 unavailableQty
    // 对于 miss item，应该将 missQty 计入 unavailableQty
    updateInventoryUnavailableQty(itemId, missQty)
    
    // ✅ 修复5：更新 stock_out_line 状态为 rejected（因为还有 miss item）
    updateStockOutLineStatus(request, "rejected")
    
    // 重新建议拣货批次（针对 miss 的数量）
    try {
        resuggestPickOrder(request.pickOrderId)
        println("Resuggested pick order for miss qty: ${missQty}")
    } catch (e: Exception) {
        println("Error during resuggest in handleMissItemWithPartialPick: ${e.message}")
    }
}

// ✅ 修复：Miss item 处理逻辑
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class])
private fun handleMissItemOnly(request: PickExecutionIssueRequest, missQty: BigDecimal) {
    println("=== HANDLING MISS ITEM ONLY (FIXED LOGIC) ===")
    println("Miss Qty: ${missQty}")
    
    val lotId = request.lotId ?: return
    val itemId = request.itemId ?: return
    val inventoryLotLine = inventoryLotLineRepository.findById(lotId).orElse(null)
    
    if (inventoryLotLine != null) {
        // ✅ 修复：Miss item 意味着剩余的所有物品都找不到
        val currentInQty = inventoryLotLine.inQty ?: BigDecimal.ZERO
        val currentOutQty = inventoryLotLine.outQty ?: BigDecimal.ZERO
        val remainingQty = currentInQty.minus(currentOutQty)
        
        // 标记批次为 unavailable
        inventoryLotLine.status = InventoryLotLineStatus.UNAVAILABLE
        inventoryLotLine.modified = LocalDateTime.now()
        inventoryLotLine.modifiedBy = "system"
        inventoryLotLineRepository.save(inventoryLotLine)
        
        println("Miss item only: Set lot ${lotId} status to UNAVAILABLE")
        println("  - Remaining qty: ${remainingQty}")
        println("  - Miss qty (user input): ${missQty}")
        println("  - Unavailable qty (should be remaining qty): ${remainingQty}")
    }
    
    // ✅ 修复：更新 inventory 表的 unavailableQty
    // 应该是剩余的数量，而不是 missQty
    val currentInQty = inventoryLotLine?.inQty ?: BigDecimal.ZERO
    val currentOutQty = inventoryLotLine?.outQty ?: BigDecimal.ZERO
    val remainingQty = currentInQty.minus(currentOutQty)
    
    // ✅ 修复：只增加剩余数量，不要重复计算 missQty
    updateInventoryUnavailableQty(itemId, remainingQty)
    
    // ✅ 修复：更新 stock_out_line 状态为 rejected
    updateStockOutLineStatus(request, "rejected")
    
    // 重新建议拣货批次
    try {
        resuggestPickOrder(request.pickOrderId)
        println("Resuggested pick order to find alternative lots for missing qty: ${missQty}")
    } catch (e: Exception) {
        println("Error during resuggest in handleMissItemOnly: ${e.message}")
    }
}

// ✅ 修复：Bad item 处理逻辑
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class])
private fun handleBadItemOnly(request: PickExecutionIssueRequest, badItemQty: BigDecimal) {
    println("=== HANDLING BAD ITEM ONLY (FIXED LOGIC) ===")
    println("Bad Item Qty: ${badItemQty}")
    
    val lotId = request.lotId ?: return
    val itemId = request.itemId ?: return
    val inventoryLotLine = inventoryLotLineRepository.findById(lotId).orElse(null)
    
    if (inventoryLotLine != null) {
        // ✅ 修复：Bad item 不减少 inQty，而是标记为 unavailable
        // 因为 bad item 意味着这些物品质量有问题，不能使用
        inventoryLotLine.status = InventoryLotLineStatus.UNAVAILABLE
        inventoryLotLine.modified = LocalDateTime.now()
        inventoryLotLine.modifiedBy = "system"
        inventoryLotLineRepository.save(inventoryLotLine)
        
        println("Bad item only: Set lot ${lotId} status to UNAVAILABLE")
    }
    
    // ✅ 修复：更新 inventory 表的 unavailableQty
    updateInventoryUnavailableQty(itemId, badItemQty)
    
    // ✅ 修复：更新 stock_out_line 状态为 rejected
    updateStockOutLineStatus(request, "rejected")
    
    // 重新建议拣货批次
    try {
        resuggestPickOrder(request.pickOrderId)
        println("Resuggested pick order for bad item qty: ${badItemQty}")
    } catch (e: Exception) {
        println("Error during resuggest in handleBadItemOnly: ${e.message}")
    }
}

// ✅ 修复：Both miss and bad item 处理逻辑
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class])
private fun handleBothMissAndBadItem(request: PickExecutionIssueRequest, missQty: BigDecimal, badItemQty: BigDecimal) {
    println("=== HANDLING BOTH MISS AND BAD ITEM (FIXED LOGIC) ===")
    println("Miss Qty: ${missQty}, Bad Item Qty: ${badItemQty}")
    
    val lotId = request.lotId ?: return
    val itemId = request.itemId ?: return
    val inventoryLotLine = inventoryLotLineRepository.findById(lotId).orElse(null)
    val totalUnavailableQty = missQty.add(badItemQty)
    
    if (inventoryLotLine != null) {
        // ✅ 修复：Miss + Bad item 不减少 inQty，而是标记为 unavailable
        inventoryLotLine.status = InventoryLotLineStatus.UNAVAILABLE
        inventoryLotLine.modified = LocalDateTime.now()
        inventoryLotLine.modifiedBy = "system"
        inventoryLotLineRepository.save(inventoryLotLine)
        
        println("Both miss and bad item: Set lot ${lotId} status to UNAVAILABLE")
        println("  - Miss Qty: ${missQty}")
        println("  - Bad Item Qty: ${badItemQty}")
        println("  - Total Unavailable Qty: ${totalUnavailableQty}")
    }
    
    // ✅ 修复：更新 inventory 表的 unavailableQty
    updateInventoryUnavailableQty(itemId, totalUnavailableQty)
    
    // ✅ 修复：更新 stock_out_line 状态为 rejected
    updateStockOutLineStatus(request, "rejected")
    
    // 重新建议拣货批次
    try {
        resuggestPickOrder(request.pickOrderId)
        println("Resuggested pick order for both miss qty: ${missQty} and bad item qty: ${badItemQty}")
    } catch (e: Exception) {
        println("Error during resuggest in handleBothMissAndBadItem: ${e.message}")
    }
}

    // ✅ 修复：正常拣货处理逻辑
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class])
    private fun handleNormalPick(request: PickExecutionIssueRequest, actualPickQty: BigDecimal) {
        println("=== HANDLING NORMAL PICK ===")
        
        // ✅ 修复：更新 stock_out_line，但不要累积 qty
        val stockOutLines = stockOutLineRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(
            request.pickOrderLineId,
            request.lotId ?: 0L
        )
        
        stockOutLines.forEach { stockOutLine ->
            // ✅ 修复：直接设置 qty 为 actualPickQty，不要累积
            val requiredQty = request.requiredQty?.toDouble() ?: 0.0
            val actualPickQtyDouble = actualPickQty.toDouble()
            val newStatus = if (actualPickQtyDouble >= requiredQty) {
                "completed"
            } else {
                "partially_completed"
            }
            
            stockOutLine.status = newStatus
            stockOutLine.qty = actualPickQtyDouble // ✅ 直接设置，不累积
            stockOutLine.modified = LocalDateTime.now()
            stockOutLine.modifiedBy = "system"
            stockOutLineRepository.save(stockOutLine)
            
            println("Updated stock out line ${stockOutLine.id}: status=${newStatus}, qty=${actualPickQtyDouble}")
        }

        // ✅ 修复：更新 inventory_lot_line 的 outQty
        val lotId = request.lotId ?: return
        val inventoryLotLine = inventoryLotLineRepository.findById(lotId).orElse(null)
        if (inventoryLotLine != null) {
            // ✅ 修复：计算新的 outQty，考虑之前的 outQty
            val currentOutQty = inventoryLotLine.outQty ?: BigDecimal.ZERO
            val previousPickedQty = currentOutQty.minus(actualPickQty) // 计算之前已拣的数量
            val newOutQty = previousPickedQty.add(actualPickQty) // 更新为新的总拣货数量
            
            inventoryLotLine.outQty = newOutQty
            inventoryLotLine.modified = LocalDateTime.now()
            inventoryLotLine.modifiedBy = "system"
            inventoryLotLineRepository.save(inventoryLotLine)
            
            println("Updated inventory lot line ${lotId} outQty: ${currentOutQty} -> ${newOutQty}")
        }
    }

    // ✅ 新方法：统一更新 inventory 表的 unavailableQty
    private fun updateInventoryUnavailableQty(itemId: Long, unavailableQty: BigDecimal) {
        try {
            println("=== INVENTORY UNAVAILABLE QTY UPDATE (TRIGGER HANDLED) ===")
            println("Item ID: ${itemId}")
            println("Expected unavailableQty to be added by trigger: ${unavailableQty}")
            println("Note: Database trigger will handle unavailableQty calculation")
            println("=========================================================")
        } catch (e: Exception) {
            println("Error in updateInventoryUnavailableQty: ${e.message}")
        }
    }

    // ✅ 修复：更新 stock_out_line 状态
    private fun updateStockOutLineStatus(request: PickExecutionIssueRequest, status: String) {
        val stockOutLines = stockOutLineRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(
            request.pickOrderLineId,
            request.lotId ?: 0L
        )
        
        stockOutLines.forEach { stockOutLine ->
            stockOutLine.status = status
            
            // ✅ FIX: Update qty to actualPickQty before setting status to rejected
            if (status == "rejected" && request.actualPickQty != null) {
                stockOutLine.qty = request.actualPickQty.toDouble()
                println("Updated stock out line ${stockOutLine.id} qty to: ${request.actualPickQty}")
            }
            
            stockOutLine.modified = LocalDateTime.now()
            stockOutLine.modifiedBy = "system"
            stockOutLineRepository.save(stockOutLine)
            
            println("Updated stock out line ${stockOutLine.id} status to: ${status}")
        }
    }
    // ✅ 修复：使用 REQUIRES_NEW 传播级别，避免事务冲突
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = [Exception::class])
    private fun resuggestPickOrder(pickOrderId: Long?) {
        if (pickOrderId != null) {
            try {
                val resuggestResult = suggestedPickLotService.resuggestPickOrder(pickOrderId)
                println("Resuggest result: ${resuggestResult.code} - ${resuggestResult.message}")
                
                if (resuggestResult.code != "SUCCESS") {
                    println("Warning: Resuggest failed: ${resuggestResult.message}")
                }
            } catch (e: Exception) {
                println("Error during resuggest: ${e.message}")
                e.printStackTrace()
                // 不重新抛出异常，避免影响主事务
            }
        }
    }

    open fun getPickExecutionIssuesByPickOrder(pickOrderId: Long): List<PickExecutionIssue> {
        return pickExecutionIssueRepository.findByPickOrderIdAndDeletedFalse(pickOrderId)
    }

    open fun getPickExecutionIssuesByPickOrderLine(pickOrderLineId: Long): List<PickExecutionIssue> {
        return pickExecutionIssueRepository.findByPickOrderLineIdAndDeletedFalse(pickOrderLineId)
    }
}