package com.ffii.fpsms.modules.stock.web

import com.ffii.fpsms.modules.stock.service.StockTakeRecordService
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.http.ResponseEntity
import com.ffii.fpsms.modules.stock.web.model.*
import org.slf4j.LoggerFactory
import com.ffii.core.response.RecordsRes
import java.time.LocalDate
@RestController
@RequestMapping("/stockTakeRecord")
class StockTakeRecordController(
    private val stockOutRecordService: StockTakeRecordService
) {
    private val logger = LoggerFactory.getLogger(StockTakeRecordController::class.java)
    /* 
    @GetMapping("/AllPickedStockOutRecordList")
    fun AllPickedStockOutRecordList(): List<AllPickedStockTakeListReponse> {
        return stockOutRecordService.AllPickedStockTakeList()
    }
    */
    @GetMapping("/AllPickedStockOutRecordList")
    fun allPickedStockOutRecordList(
        @RequestParam(required = false, defaultValue = "0") pageNum: Int,
        @RequestParam(required = false, defaultValue = "6") pageSize: Int,
        @RequestParam(required = false) sectionDescription: String?,
        @RequestParam(required = false) stockTakeSections: String?,
        @RequestParam(required = false) status: String?,
        @RequestParam(required = false) area: String?,
        @RequestParam(required = false) storeId: String?,
        @RequestParam(required = false, defaultValue = "false") onlyLatestRound: Boolean
    ): RecordsRes<AllPickedStockTakeListReponse> {
        var all = stockOutRecordService.AllPickedStockTakeList()
        if (sectionDescription != null && sectionDescription != "All") {
            all = all.filter { it.stockTakeSectionDescription == sectionDescription }
        }
        if (!stockTakeSections.isNullOrBlank()) {
            val sections = stockTakeSections.split(",").map { it.trim() }.filter { it.isNotBlank() }
            if (sections.isNotEmpty()) {
                all = all.filter { session ->
                    sections.any { part ->
                        session.stockTakeSession.equals(part, ignoreCase = true) ||
                        session.stockTakeSession.contains(part, ignoreCase = true)
                    }
                }
            }
        }
        if (!status.isNullOrBlank() && status != "All") {
            val normalizedStatus = status.trim().lowercase()
            val acceptedStatuses = when (normalizedStatus) {
                "stocktaking" -> setOf("stocktaking", "processing", "in_progress")
                else -> setOf(normalizedStatus)
            }
            all = all.filter { item ->
                val itemStatus = item.status.trim().lowercase()
                itemStatus in acceptedStatuses
            }
        }
        if (!area.isNullOrBlank()) {
            val areaKeyword = area.trim()
            all = all.filter { it.warehouseArea?.contains(areaKeyword, ignoreCase = true) == true }
        }
        if (!storeId.isNullOrBlank() && storeId != "All") {
            val storeIdKeyword = storeId.trim()
            all = all.filter {
                it.storeId?.equals(storeIdKeyword, ignoreCase = true) == true ||
                    it.storeId?.contains(storeIdKeyword, ignoreCase = true) == true
            }
        }
        if (onlyLatestRound) {
            val latestRoundKey = stockOutRecordService.resolveGlobalLatestStockTakeRoundKey()
            all = if (latestRoundKey == null || latestRoundKey <= 0L) {
                emptyList()
            } else {
                all.filter { (it.stockTakeRoundId ?: it.stockTakeId) == latestRoundKey }
            }
        }
        val total = all.size
        val fromIndex = pageNum * pageSize
        val toIndex = minOf(fromIndex + pageSize, total)
        val pageList = if (fromIndex >= total) emptyList() else all.subList(fromIndex, toIndex)
        return RecordsRes(pageList, total)
    }

    @GetMapping("/latestStockTakeRoundMeta")
    fun latestStockTakeRoundMeta(): LatestStockTakeRoundMetaResponse {
        return stockOutRecordService.getGlobalLatestStockTakeRoundMeta()
    }

    @GetMapping("/approverInventoryLotDetailsAll")
    fun getApproverInventoryLotDetailsAll(
        @RequestParam(required = false) stockTakeId: Long?,                    // 可选：限定某个 stockTake
        @RequestParam(required = false, defaultValue = "0") pageNum: Int,     // 分页页码（从 0 开始）
        @RequestParam(required = false, defaultValue = "100") pageSize: Int,   // 每页多少条，测试时可调大
        @RequestParam(required = false) itemKeyword: String?,
        @RequestParam(required = false) sectionDescription: String?,
        @RequestParam(required = false) stockTakeSections: String?
    ): RecordsRes<InventoryLotDetailResponse> {
        return stockOutRecordService.getApproverInventoryLotDetailsAll(
            stockTakeId = stockTakeId,
            pageNum = pageNum,
            pageSize = pageSize,

            itemKeyword = itemKeyword,
            sectionDescription = sectionDescription,
            stockTakeSections = stockTakeSections
        )
    }
    @GetMapping("/approverInventoryLotDetailsAllPending")
    fun getApproverInventoryLotDetailsAllPending(
        @RequestParam(required = false) stockTakeId: Long?,
        @RequestParam(required = false, defaultValue = "0") pageNum: Int,
        @RequestParam(required = false, defaultValue = "2147483647") pageSize: Int,
        @RequestParam(required = false) itemKeyword: String?,
        @RequestParam(required = false) sectionDescription: String?,
        @RequestParam(required = false) stockTakeSections: String?,
        @RequestParam(required = false) warehouseKeyword: String?,
        @RequestParam(required = false) variancePercentTolerance: java.math.BigDecimal?,
        @RequestParam(required = false) varianceFilterInclusive: Boolean?,
        @RequestParam(required = false) varianceFilterStrict: Boolean?,
    ): RecordsRes<InventoryLotDetailResponse> {
        return stockOutRecordService.getApproverInventoryLotDetailsAll(
            stockTakeId = stockTakeId,
            pageNum = pageNum,
            pageSize = pageSize,
            approvalView = "pending",
            itemKeyword = itemKeyword,
            sectionDescription = sectionDescription,
            stockTakeSections = stockTakeSections,
            warehouseKeyword = warehouseKeyword,
            variancePercentTolerance = variancePercentTolerance,
            varianceFilterInclusive = varianceFilterInclusive,
            varianceFilterStrict = varianceFilterStrict,
        )
    }
    @GetMapping("/approverInventoryLotDetailsAllApproved")
    fun getApproverInventoryLotDetailsAllApproved(
        @RequestParam(required = false) stockTakeId: Long?,
        @RequestParam(required = false, defaultValue = "0") pageNum: Int,
        @RequestParam(required = false, defaultValue = "50") pageSize: Int,
        @RequestParam(required = false) itemKeyword: String?,
        @RequestParam(required = false) sectionDescription: String?,
        @RequestParam(required = false) stockTakeSections: String?,
        @RequestParam(required = false) warehouseKeyword: String?,
        @RequestParam(required = false) variancePercentTolerance: java.math.BigDecimal?,
        @RequestParam(required = false) varianceFilterInclusive: Boolean?,
        @RequestParam(required = false) varianceFilterStrict: Boolean?,
    ): RecordsRes<InventoryLotDetailResponse> {
        return stockOutRecordService.getApproverInventoryLotDetailsAll(
            stockTakeId = stockTakeId,
            pageNum = pageNum,
            pageSize = pageSize,
            approvalView = "approved",
            itemKeyword = itemKeyword,
            sectionDescription = sectionDescription,
            stockTakeSections = stockTakeSections,
            warehouseKeyword = warehouseKeyword,
            variancePercentTolerance = variancePercentTolerance,
            varianceFilterInclusive = varianceFilterInclusive,
            varianceFilterStrict = varianceFilterStrict,
        )
    }
    @GetMapping("/AllApproverStockTakeList")
    fun AllApproverStockTakeList(): List<AllPickedStockTakeListReponse> {
        return stockOutRecordService.AllApproverStockTakeList()
    }
    @GetMapping("/LatestApproverStockTakeHeader")
    fun latestApproverStockTakeHeader(): ResponseEntity<AllPickedStockTakeListReponse> {
        val header = stockOutRecordService.getLatestApproverStockTakeHeader()
            ?: return ResponseEntity.notFound().build()
        return ResponseEntity.ok(header)
    }
    @GetMapping("/inventoryLotDetailsBySectionNotMatch")
    fun getInventoryLotDetailsByStockTakeSectionNotMatch(
        @RequestParam stockTakeSection: String,
        @RequestParam(required = false) stockTakeId: Long?,
        @RequestParam(required = false) stockTakeRoundId: Long?,
        @RequestParam(required = false, defaultValue = "0") pageNum: Int,
        @RequestParam(required = false) pageSize: Int?
    ): RecordsRes<InventoryLotDetailResponse> {
        val actualPageSize = pageSize ?: Int.MAX_VALUE
        return stockOutRecordService.getInventoryLotDetailsByStockTakeSectionNotMatch(
            stockTakeSection,
            stockTakeId,
            stockTakeRoundId,
            pageNum,
            actualPageSize
        )
    }
    
    @GetMapping("/inventoryLotDetails")
    fun getInventoryLotDetailsByWarehouseCode(
        @RequestParam warehouseCode: String
    ): List<InventoryLotDetailResponse> {
        return stockOutRecordService.getInventoryLotDetailsByWarehouseCode(warehouseCode)
    }
    
    @GetMapping("/inventoryLotDetailsBySection")
    fun getInventoryLotDetailsByStockTakeSection(
        @RequestParam stockTakeSection: String,
        @RequestParam(required = false) stockTakeId: Long?,
        @RequestParam(required = false) stockTakeRoundId: Long?,
        @RequestParam(required = false, defaultValue = "0") pageNum: Int,
        @RequestParam(required = false, defaultValue = "10") pageSize: Int
    ): RecordsRes<InventoryLotDetailResponse> {
        return stockOutRecordService.getInventoryLotDetailsByStockTakeSection(
            stockTakeSection,
            stockTakeId,
            stockTakeRoundId,
            pageNum,
            pageSize
        )
    }
    
    @PostMapping("/saveStockTakeRecord")
    fun saveStockTakeRecord(
        @RequestBody request: SaveStockTakeRecordRequest,
        @RequestParam stockTakeId: Long,
        @RequestParam stockTakerId: Long
    ): ResponseEntity<Any> {
        return try {
            val savedRecord = stockOutRecordService.saveStockTakeRecord(request, stockTakeId, stockTakerId)
            logger.info("Successfully saved stock take record: ${savedRecord.id}")
            ResponseEntity.ok(savedRecord)
        } catch (e: IllegalArgumentException) {
            logger.warn("Validation error: ${e.message}")
            ResponseEntity.badRequest().body(mapOf(
                "error" to "VALIDATION_ERROR",
                "message" to (e.message ?: "Validation failed")
            ))
        } catch (e: Exception) {
            logger.error("Error saving stock take record", e)
            ResponseEntity.status(500).body(mapOf(
                "error" to "INTERNAL_ERROR",
                "message" to (e.message ?: "Failed to save stock take record")
            ))
        }
    }
    
    @PostMapping("/batchSaveStockTakeRecords")
    fun batchSaveStockTakeRecords(
        @RequestBody request: BatchSaveStockTakeRecordRequest
    ): ResponseEntity<Any> {
        return try {
            val result = stockOutRecordService.batchSaveStockTakeRecords(request)
            logger.info("Batch save completed: success=${result.successCount}, errors=${result.errorCount}")
            ResponseEntity.ok(result)
        } catch (e: IllegalArgumentException) {
            logger.warn("Validation error: ${e.message}")
            ResponseEntity.badRequest().body(mapOf(
                "error" to "VALIDATION_ERROR",
                "message" to (e.message ?: "Validation failed")
            ))
        } catch (e: Exception) {
            logger.error("Error batch saving stock take records", e)
            ResponseEntity.status(500).body(mapOf(
                "error" to "INTERNAL_ERROR",
                "message" to (e.message ?: "Failed to batch save stock take records")
            ))
        }
    }

    @PostMapping("/batchSavePickerStockTakeInputs")
    fun batchSavePickerStockTakeInputs(
        @RequestBody request: BatchSavePickerStockTakeInputRequest
    ): ResponseEntity<Any> {
        return try {
            val result = stockOutRecordService.batchSavePickerStockTakeInputs(request)
            logger.info(
                "Batch save picker inputs: success=${result.successCount}, errors=${result.errorCount}"
            )
            ResponseEntity.ok(result)
        } catch (e: IllegalArgumentException) {
            logger.warn("Validation error: ${e.message}")
            ResponseEntity.badRequest().body(mapOf(
                "error" to "VALIDATION_ERROR",
                "message" to (e.message ?: "Validation failed")
            ))
        } catch (e: Exception) {
            logger.error("Error batch saving picker stock take inputs", e)
            ResponseEntity.status(500).body(mapOf(
                "error" to "INTERNAL_ERROR",
                "message" to (e.message ?: "Failed to batch save picker stock take inputs")
            ))
        }
    }
    
    @GetMapping("/checkAndUpdateStockTakeStatus")
    fun checkAndUpdateStockTakeStatus(
        @RequestParam stockTakeId: Long,
        @RequestParam stockTakeSection: String
    ): ResponseEntity<Any> {
        return try {
            val result = stockOutRecordService.checkAndUpdateStockTakeStatus(stockTakeId, stockTakeSection)
            ResponseEntity.ok(result)
        } catch (e: Exception) {
            logger.error("Error checking and updating stock take status", e)
            ResponseEntity.status(500).body(
                mapOf(
                    "error" to "INTERNAL_ERROR",
                    "message" to (e.message ?: "Failed to check and update stock take status")
                )
            )
        }
    }
    
    @PostMapping("/saveApproverStockTakeRecord")
    fun saveApproverStockTakeRecord(
        @RequestBody request: SaveApproverStockTakeRecordRequest,
        @RequestParam stockTakeId: Long
    ): ResponseEntity<Any> {
        return try {
            val savedRecord = stockOutRecordService.saveApproverStockTakeRecord(request, stockTakeId)
            logger.info("Successfully saved approver stock take record: ${savedRecord.id}")
            ResponseEntity.ok(savedRecord)
        } catch (e: IllegalArgumentException) {
            logger.warn("Validation error: ${e.message}")
            ResponseEntity.badRequest().body(mapOf(
                "error" to "VALIDATION_ERROR",
                "message" to (e.message ?: "Validation failed")
            ))
        } catch (e: Exception) {
            logger.error("Error saving approver stock take record", e)
            ResponseEntity.status(500).body(mapOf(
                "error" to "INTERNAL_ERROR",
                "message" to (e.message ?: "Failed to save approver stock take record")
            ))
        }
    }

    @PostMapping("/batchSaveApproverStockTakeRecords")
    fun batchSaveApproverStockTakeRecords(
        @RequestBody request: BatchSaveApproverStockTakeRecordRequest
    ): ResponseEntity<Any> {
        return try {
            val result = stockOutRecordService.batchSaveApproverStockTakeRecords(request)
            logger.info("Batch approver save completed: success=${result.successCount}, errors=${result.errorCount}")
            ResponseEntity.ok(result)
        } catch (e: IllegalArgumentException) {
            logger.warn("Validation error: ${e.message}")
            ResponseEntity.badRequest().body(mapOf(
                "error" to "VALIDATION_ERROR",
                "message" to (e.message ?: "Validation failed")
            ))
        } catch (e: Exception) {
            logger.error("Error batch saving approver stock take records", e)
            ResponseEntity.status(500).body(mapOf(
                "error" to "INTERNAL_ERROR",
                "message" to (e.message ?: "Failed to batch save approver stock take records")
            ))
        }
    }
    @PostMapping("/batchSaveApproverStockTakeRecordsAll")
    fun batchSaveApproverStockTakeRecordsAll(
        @RequestBody request: BatchSaveApproverStockTakeAllRequest
    ): ResponseEntity<Any> {
        return try {
            val result = stockOutRecordService.batchSaveApproverStockTakeRecordsAll(request)
            logger.info("Batch approver save all completed: success=${result.successCount}, errors=${result.errorCount}")
            ResponseEntity.ok(result)
        } catch (e: IllegalArgumentException) {
            logger.warn("Validation error: ${e.message}")
            ResponseEntity.badRequest().body(mapOf(
                "error" to "VALIDATION_ERROR",
                "message" to (e.message ?: "Validation failed")
            ))
        } catch (e: Exception) {
            logger.error("Error batch saving approver stock take records all", e)
            ResponseEntity.status(500).body(mapOf(
                "error" to "INTERNAL_ERROR",
                "message" to (e.message ?: "Failed to batch save approver stock take records all")
            ))
        }
    }
    @PostMapping("/batchSaveApproverStockTakeRecordsByIds")
    fun batchSaveApproverStockTakeRecordsByIds(
        @RequestBody request: BatchSaveApproverStockTakeByIdsRequest
    ): ResponseEntity<Any> {
        return try {
            val result = stockOutRecordService.batchSaveApproverStockTakeRecordsByIds(request)
            logger.info("Batch approver save by ids completed: success=${result.successCount}, errors=${result.errorCount}")
            ResponseEntity.ok(result)
        } catch (e: IllegalArgumentException) {
            logger.warn("Validation error: ${e.message}")
            ResponseEntity.badRequest().body(mapOf(
                "error" to "VALIDATION_ERROR",
                "message" to (e.message ?: "Validation failed")
            ))
        } catch (e: Exception) {
            logger.error("Error batch saving approver stock take records by ids", e)
            ResponseEntity.status(500).body(mapOf(
                "error" to "INTERNAL_ERROR",
                "message" to (e.message ?: "Failed to batch save approver stock take records by ids")
            ))
        }
    }
    @PostMapping("/updateStockTakeRecordStatusToNotMatch")
    fun updateStockTakeRecordStatusToNotMatch(
        @RequestParam stockTakeRecordId: Long
    ): ResponseEntity<Any> {
        return try {
            val result = stockOutRecordService.updateStockTakeRecordStatusToNotMatch(stockTakeRecordId)
            ResponseEntity.ok(result)
        } catch (e: Exception) {
            logger.error("Error updating stock take record status to not match", e)
            ResponseEntity.status(500).body(mapOf(
                "error" to "INTERNAL_ERROR",
                "message" to (e.message ?: "Failed to update stock take record status to not match")
            ))
        }
    }


    @GetMapping("/searchStockTransactions")
    fun searchStockTransactions(
        @RequestParam(required = false) itemCode: String?,
        @RequestParam(required = false) itemName: String?,
        @RequestParam(required = false) type: String?,
        @RequestParam(required = false) startDate: LocalDate?,
        @RequestParam(required = false) endDate: LocalDate?,
        @RequestParam(required = false, defaultValue = "0") pageNum: Int,
        @RequestParam(required = false, defaultValue = "100") pageSize: Int
    ): RecordsRes<StockTransactionResponse> {
        val request = SearchStockTransactionRequest(
            startDate = startDate,
            endDate = endDate,
            itemCode = itemCode,
            itemName = itemName,
            type = type,
            pageNum = pageNum,
            pageSize = pageSize
        )
        return stockOutRecordService.searchStockTransactions(request)
    }
}