package com.ffii.fpsms.modules.deliveryOrder.service

import com.ffii.core.support.JdbcDao
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRepository
import com.ffii.fpsms.modules.deliveryOrder.enums.DoPickOrderStatus
import com.ffii.fpsms.modules.deliveryOrder.web.models.LaneBtn
import com.ffii.fpsms.modules.deliveryOrder.web.models.LaneRow
import com.ffii.fpsms.modules.deliveryOrder.web.models.StoreLaneSummary
import com.ffii.fpsms.modules.deliveryOrder.web.models.DoPickOrderSummaryItem
import org.springframework.stereotype.Service
import java.time.LocalDate
import java.time.LocalTime
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository
import com.ffii.fpsms.modules.pickOrder.entity.TruckRepository
@Service
class DoPickOrderQueryService(
    private val doPickOrderRepository: DoPickOrderRepository,
    private val jdbcDao: JdbcDao,
    private val doPickOrderRecordRepository: DoPickOrderRecordRepository,
    private val truckRepository: TruckRepository
) {
    
    fun getSummaryByStore(storeId: String, requiredDate: LocalDate?, releaseType: String): StoreLaneSummary {
        val targetDate = requiredDate ?: LocalDate.now()
    
        val actualStoreId = when (storeId) {
            "2/F" -> "2/F"
            "4/F" -> "4/F"
            else -> storeId
        }
    
        // Active: do_pick_order
        val activeRecords = doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
            actualStoreId,
            targetDate,
            listOf(DoPickOrderStatus.pending, DoPickOrderStatus.released, DoPickOrderStatus.completed)
        )
    
        val filteredActiveRecordsByReleaseType = when (releaseType.lowercase()) {
            "batch" -> activeRecords.filter { it.releaseType == "batch" }
            "single" -> activeRecords.filter { it.releaseType == "single" }
            else -> activeRecords
        }
    
        // Completed archive: do_pick_order_record
        val completedRecords = doPickOrderRecordRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
            actualStoreId,
            targetDate,
            listOf(DoPickOrderStatus.completed)
        )
    
        val filteredCompletedRecordsByReleaseType = when (releaseType.lowercase()) {
            "batch" -> completedRecords.filter { it.releaseType == "batch" }
            "single" -> completedRecords.filter { it.releaseType == "single" }
            else -> completedRecords
        }
    
        // non-issue filter
        val filteredActiveRecords = filteredActiveRecordsByReleaseType.filter { doPickOrder ->
            val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!)
            if (!hasNonIssueLines) {
                println("    DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues")
            }
            hasNonIssueLines
        }
    
        val filteredCompletedRecords = filteredCompletedRecordsByReleaseType.filter { record ->
            val hasNonIssueLines = checkDoPickOrderRecordHasNonIssueLines(record.id!!)
            if (!hasNonIssueLines) {
                println("    DEBUG: Filtering out DoPickOrderRecord ${record.id} - all lines are issues")
            }
            hasNonIssueLines
        }
    
        // 合并为 summary item
        // 你的要求是 handler 来源用 delivery_order_pick_order.handlerName
        // 所以 active records 用 it.handlerName；completed records 这里给 null，避免混入 archive 来源
        val allRecords = filteredActiveRecords.map {
            DoPickOrderSummaryItem(
                truckDepartureTime = it.truckDepartureTime,
                truckLanceCode = it.truckLanceCode,
                loadingSequence = if (actualStoreId == "4/F") it.loadingSequence else null,
                handledBy = it.handledBy,
                handlerName = it.handlerName
            )
        } + filteredCompletedRecords.map {
            DoPickOrderSummaryItem(
                truckDepartureTime = it.truckDepartureTime,
                truckLanceCode = it.truckLanceCode,
                loadingSequence = if (actualStoreId == "4/F") it.loadingSequence else null,
                handledBy = it.handledBy,
                handlerName = null
            )
        }
    
        val defaultTruckId = 5577L
        val defaultTruck = truckRepository.findById(defaultTruckId).orElse(null)
        val defaultTruckLaneCode = defaultTruck?.truckLanceCode ?: ""
    
        val grouped = if (actualStoreId == "4/F") {
            allRecords.groupBy { Triple(it.truckDepartureTime, it.truckLanceCode, it.loadingSequence) }
        } else {
            allRecords.groupBy { Pair(it.truckDepartureTime, it.truckLanceCode) }
        }.mapValues { (_, list) ->
            val mergedHandlerNames = list
                .mapNotNull { it.handlerName?.trim()?.takeIf { n -> n.isNotEmpty() } }
                .distinct()
                .sorted()
                .joinToString(",")
    
            LaneBtn(
                truckLanceCode = list.first().truckLanceCode ?: "",
                loadingSequence = if (actualStoreId == "4/F") list.first().loadingSequence else null,
                unassigned = list.count { it.handledBy == null },
                total = list.size,
                handlerName = mergedHandlerNames.ifBlank { null }
            )
        }
    
        val filteredGrouped = grouped.filter { (_, laneBtn) ->
            laneBtn.truckLanceCode != defaultTruckLaneCode
        }
    
        val groupedByTime: Map<LocalTime?, List<Map.Entry<Any, LaneBtn>>> =
    filteredGrouped.entries.groupBy { entry: Map.Entry<Any, LaneBtn> ->
        when (val key = entry.key) {
            is Triple<*, *, *> -> key.first as? LocalTime
            is Pair<*, *> -> key.first as? LocalTime
            else -> null
        }
    }

val timeGroups = groupedByTime
    .mapValues { (_, entries: List<Map.Entry<Any, LaneBtn>>) ->
        entries.map { it.value }
            .sortedWith(
                compareByDescending<LaneBtn> { it.unassigned }
                    .thenBy { it.truckLanceCode }
                    .thenBy { it.loadingSequence ?: 999 }
            )
    }
    .filterValues { lanes -> lanes.isNotEmpty() }
    .toSortedMap(compareBy { it })
    .entries
    .take(4)
    .map { (time, lanes) ->
        LaneRow(
            truckDepartureTime = time?.toString() ?: "",
            lanes = lanes
        )
    }
    
        val defaultTruckCandidates = doPickOrderRepository.findByRequiredDeliveryDateAndTicketStatusIn(
            targetDate,
            listOf(DoPickOrderStatus.pending, DoPickOrderStatus.released)
        )
    
        val defaultTruckCount = defaultTruckCandidates.count {
            it.storeId == null && it.truckLanceCode == "車線-X"
        }
    
        return StoreLaneSummary(
            storeId = storeId,
            rows = timeGroups,
            defaultTruckCount = defaultTruckCount
        )
    }
    
    
    private fun checkDoPickOrderHasNonIssueLines(doPickOrderId: Long): Boolean {
        return try {
            val totalLinesSql = """
                SELECT COUNT(*) as total_lines
                FROM fpsmsdb.do_pick_order_line dpol
                WHERE dpol.do_pick_order_id = :doPickOrderId 
                AND dpol.deleted = 0
            """.trimIndent()
            
            val totalLinesResult = jdbcDao.queryForList(totalLinesSql, mapOf("doPickOrderId" to doPickOrderId))
            val totalLines = (totalLinesResult.firstOrNull()?.get("total_lines") as? Number)?.toInt() ?: 0
            
            if (totalLines == 0) {
                return true
            }
            
            val nonIssueLinesSql = """
                SELECT COUNT(*) as non_issue_lines
                FROM fpsmsdb.do_pick_order_line dpol
                WHERE dpol.do_pick_order_id = :doPickOrderId 
                AND dpol.deleted = 0
                AND (dpol.status IS NULL OR dpol.status != 'issue')
            """.trimIndent()
            
            val nonIssueLinesResult = jdbcDao.queryForList(nonIssueLinesSql, mapOf("doPickOrderId" to doPickOrderId))
            val nonIssueLines = (nonIssueLinesResult.firstOrNull()?.get("non_issue_lines") as? Number)?.toInt() ?: 0
            
            nonIssueLines > 0
        } catch (e: Exception) {
            println("❌ Error checking non-issue lines: ${e.message}")
            true
        }
    }
    
    // Add new method to check non-issue lines for records
    private fun checkDoPickOrderRecordHasNonIssueLines(recordId: Long): Boolean {
        return try {
            // First get the record_id from do_pick_order_record
            val recordSql = """
                SELECT record_id 
                FROM fpsmsdb.do_pick_order_record dpor
                WHERE dpor.id = :recordId
            """.trimIndent()
            
            val recordResult = jdbcDao.queryForList(recordSql, mapOf("recordId" to recordId))
            val recordIdValue = (recordResult.firstOrNull()?.get("record_id") as? Number)?.toLong()
            
            if (recordIdValue == null) {
                return true  // If no record_id, assume it's valid
            }
            
            // Check do_pick_order_line_record table
            val totalLinesSql = """
                SELECT COUNT(*) as total_lines
                FROM fpsmsdb.do_pick_order_line_record dpolr
                WHERE dpolr.record_id = :recordId 
                AND dpolr.deleted = 0
            """.trimIndent()
            
            val totalLinesResult = jdbcDao.queryForList(totalLinesSql, mapOf("recordId" to recordIdValue))
            val totalLines = (totalLinesResult.firstOrNull()?.get("total_lines") as? Number)?.toInt() ?: 0
            
            if (totalLines == 0) {
                return true
            }
            
            val nonIssueLinesSql = """
                SELECT COUNT(*) as non_issue_lines
                FROM fpsmsdb.do_pick_order_line_record dpolr
                WHERE dpolr.record_id = :recordId 
                AND dpolr.deleted = 0
                AND (dpolr.status IS NULL OR dpolr.status != 'issue')
            """.trimIndent()
            
            val nonIssueLinesResult = jdbcDao.queryForList(nonIssueLinesSql, mapOf("recordId" to recordIdValue))
            val nonIssueLines = (nonIssueLinesResult.firstOrNull()?.get("non_issue_lines") as? Number)?.toInt() ?: 0
            
            nonIssueLines > 0
        } catch (e: Exception) {
            println("❌ Error checking non-issue lines for record: ${e.message}")
            true
        }
    }
}