package com.ffii.fpsms.modules.pickOrder.web

import com.ffii.core.response.RecordsRes
import com.ffii.core.utils.CriteriaArgsBuilder
import com.ffii.core.utils.PagingUtils
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository
import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderInfo
import com.ffii.fpsms.modules.pickOrder.service.PickOrderService
import com.ffii.fpsms.modules.pickOrder.service.PickOrderWorkbenchService
import com.ffii.fpsms.modules.pickOrder.web.models.*
import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderRequest
import com.ffii.fpsms.modules.pickOrder.web.models.ConsoPickOrderResponse
import com.ffii.fpsms.modules.pickOrder.web.models.ReleaseConsoPickOrderRequest
import com.ffii.fpsms.modules.pickOrder.web.models.SearchPickOrderRequest
import com.ffii.fpsms.modules.pickOrder.web.models.SavePickOrderGroupRequest
import jakarta.servlet.http.HttpServletRequest
import com.ffii.fpsms.modules.pickOrder.web.models.HierarchicalPickOrderResponse
import jakarta.validation.Valid
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.time.DateTimeException
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.LocalDate
import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderGroupInfo
import com.ffii.fpsms.modules.pickOrder.web.models.GetPickOrderInfoResponse
import com.ffii.fpsms.modules.pickOrder.web.models.LotSubstitutionConfirmRequest
import com.ffii.fpsms.modules.deliveryOrder.service.DoWorkbenchMainService
@RestController
@RequestMapping("/pickOrder")
class PickOrderController(
    private val pickOrderService: PickOrderService,
    private val pickOrderWorkbenchService: PickOrderWorkbenchService,
    private val pickOrderRepository: PickOrderRepository,
    private val doWorkbenchMainService: DoWorkbenchMainService,
) {
    @GetMapping("/list")
    fun allPickOrders(): List<PickOrderInfo> {
        return pickOrderService.allPickOrders();
    }

    @GetMapping("/getRecordByPage")
    fun allPickOrdersByPage(@ModelAttribute request: SearchPickOrderRequest): RecordsRes<PickOrderInfo> {
        return pickOrderService.allPickOrdersByPage(request);
    }

    @GetMapping("/getRecordByPageWithStock")
    fun getPickOrdersWithStockBalanceByPage(@ModelAttribute request: SearchPickOrderRequest): RecordsRes<GetPickOrderInfo> {
        return pickOrderService.getPickOrdersWithStockBalanceByPage(request);
    }

    @GetMapping("/getRecordByPage-conso")
    fun allConsoPickOrdersByPage(request: HttpServletRequest): RecordsRes<Map<String, Any>> {
        val criteriaArgs = CriteriaArgsBuilder.withRequest(request)
            .addStringLike("consoCode")
            .addString("status")
            .addString("assignTo")
            .build()
        val pageSize = request.getParameter("pageSize")?.toIntOrNull() ?: 10 // Default to 10 if not provided
        val pageNum = request.getParameter("pageNum")?.toIntOrNull() ?: 1 // Default to 1 if not provided
        val fullList = pickOrderService.getConsoPickOrderList(criteriaArgs)
        val paginatedList = PagingUtils.getPaginatedList(fullList, pageSize, pageNum)
        return RecordsRes(paginatedList, fullList.size)
    }

    @PostMapping("/assign")
    fun assignPickOrders(@RequestBody request: Map<String, Any>): MessageResponse {
        val pickOrderIds = (request["pickOrderIds"] as List<*>).map { it.toString().toLong() }
        val assignTo = request["assignTo"].toString().toLong()
        return pickOrderService.assignPickOrders(pickOrderIds, assignTo)
    }

    @PostMapping("/cancel")
    fun cancelPickOrders(@RequestBody request: Map<String, Any>): MessageResponse {
        val pickOrderIds = (request["pickOrderIds"] as List<*>).map { it.toString().toLong() }
        return pickOrderService.cancelPickOrders(pickOrderIds)
    }

    @PostMapping("/workbench/assign-v2")
    fun assignPickOrdersWorkbenchV2(@RequestBody request: Map<String, Any>): MessageResponse {
        val pickOrderIds = (request["pickOrderIds"] as List<*>).map { it.toString().toLong() }
        val assignTo = request["assignTo"].toString().toLong()
        return pickOrderWorkbenchService.assignPickOrdersV2(pickOrderIds, assignTo)
    }

    @PostMapping("/workbench/release-v2")
    fun releasePickOrdersWorkbenchV2(@RequestBody request: Map<String, Any>): MessageResponse {
        val pickOrderIds = (request["pickOrderIds"] as List<*>).map { it.toString().toLong() }
        val assignTo = request["assignTo"].toString().toLong()
        return pickOrderWorkbenchService.releasePickOrdersV2(pickOrderIds, assignTo)
    }

    @GetMapping("/workbench/all-lots-hierarchical/{userId}")
    fun getAllPickOrderLotsHierarchicalWorkbenchConsumable(@PathVariable userId: Long): Map<String, Any?> {
        return pickOrderWorkbenchService.getAllPickOrderLotsWithDetailsHierarchicalWorkbench(userId)
    }

    @GetMapping("/workbench/line-detail-v2/{pickOrderLineId}")
    fun getWorkbenchPickOrderLineDetailV2(@PathVariable pickOrderLineId: Long): List<PickOrderLineLotDetailResponse> {
        return pickOrderWorkbenchService.getWorkbenchPickOrderLineLotDetailsV2(pickOrderLineId)
    }

    @PostMapping("/workbench/suggest-v2/{pickOrderId}")
    fun suggestPickOrderWorkbenchV2(
        @PathVariable pickOrderId: Long,
        @RequestBody request: Map<String, Any>,
    ): MessageResponse {
        val userId = request["userId"]?.toString()?.toLongOrNull()
            ?: request["assignTo"]?.toString()?.toLongOrNull()
            ?: return MessageResponse(
                id = pickOrderId,
                name = "Workbench suggest v2 failed",
                code = "ERROR",
                type = "pickorder_workbench",
                message = "userId is required",
                errorPosition = null
            )
        return pickOrderWorkbenchService.suggestPickOrderV2(pickOrderId, userId)
    }

    // Release Pick Orders (without consoCode)
    @PostMapping("/release")
    fun releasePickOrders(@RequestBody request: Map<String, Any>): MessageResponse {
        val pickOrderIds = (request["pickOrderIds"] as List<*>).map { it.toString().toLong() }
        val assignTo = request["assignTo"].toString().toLong()
        return pickOrderService.releasePickOrders(pickOrderIds, assignTo)
    }

    @GetMapping("/get-pickorder-line-byPage")
    fun getPickOrderLine(request: HttpServletRequest): RecordsRes<Map<String, Any>> {
        val criteriaArgs = CriteriaArgsBuilder.withRequest(request)
            .addString("consoCode")
            .build()
        val pageSize = request.getParameter("pageSize")?.toIntOrNull() ?: 10 // Default to 10 if not provided
        val pageNum = request.getParameter("pageNum")?.toIntOrNull() ?: 1 // Default to 1 if not provided
        val fullList = pickOrderService.getPickOrderLine(criteriaArgs)
        val paginatedList = PagingUtils.getPaginatedList(fullList, pageSize, pageNum)
        return RecordsRes(paginatedList, fullList.size)
    }

    // Consolidating Pick Orders
    @PostMapping("/conso")
    fun consoPickOrders(@Valid @RequestBody request: ConsoPickOrderRequest): List<PickOrderInfo> {
        return pickOrderService.consoPickOrders(request)
    }

    @PostMapping("/deconso")
    fun deconsoPickOrders(@Valid @RequestBody request: ConsoPickOrderRequest): List<PickOrderInfo> {
        return pickOrderService.deconsoPickOrders(request)
    }

    @GetMapping("/consoDetail/{consoCode}")
    fun consoPickOrderDetail(@PathVariable consoCode: String): ConsoPickOrderResponse {
        return pickOrderService.consoPickOrderDetail(consoCode);
    }

    // Release Pick Order
    @GetMapping("/pre-release-info/{consoCode}")
    fun releaseConsoPickOrderInfo(@PathVariable consoCode: String): ReleasePickOrderInfoResponse {
        return pickOrderService.releaseConsoPickOrderInfo(consoCode);
    }

    // TODO:
    @GetMapping("/detail/{ids}")
    fun getPickOrdersInfo(@PathVariable ids: List<Long>): GetPickOrderInfoResponse {
        return pickOrderService.getPickOrdersInfo(ids);
    }

    @GetMapping("/detail")
    fun getAllPickOrdersInfo(@RequestParam(required = false) userId: Long?): GetPickOrderInfoResponse {
        return pickOrderService.getAllPickOrdersInfo(userId)
    }

    @PostMapping("/releaseConso")
    fun releaseConsoPickOrderAction(@Valid @RequestBody request: ReleaseConsoPickOrderRequest): ReleasePickOrderInfoResponse {
        return pickOrderService.releaseConsoPickOrderAction(request)
    }

    @PostMapping("/release-assigned")
    fun releaseAssignedPickOrders(@RequestBody request: Map<String, Any>): MessageResponse {
        val pickOrderIds = (request["pickOrderIds"] as List<*>).map { it.toString().toLong() }
        val assignTo = request["assignTo"].toString().toLong()
        return pickOrderService.releaseAssignedPickOrders(pickOrderIds, assignTo)
    }

    // Start Pick Order
    @GetMapping("/pickConso/{consoCode}")
    fun pickConsoPickOrderInfo(@PathVariable consoCode: String): ReleasePickOrderInfoResponse {
        return pickOrderService.releaseConsoPickOrderInfo(consoCode);
    }

    @PostMapping("/consoPickOrder/complete/{consoCode}")
    fun completeConsoPickOrders(@PathVariable consoCode: String): MessageResponse {
        return pickOrderService.completeStockOut(consoCode)
    }

    @PostMapping("/create")
    fun create(@Valid @RequestBody request: SavePickOrderRequest): MessageResponse {
        return pickOrderService.create(request)
    }

    @GetMapping("/lot-details/{pickOrderLineId}")
    fun getPickOrderLineLotDetails(@PathVariable pickOrderLineId: Long): List<PickOrderLineLotDetailResponse> {
        return pickOrderService.getPickOrderLineLotDetails(pickOrderLineId);
    }
    @GetMapping("/lot-details-by-do-pick-order-record/{doPickOrderRecordId}")
    fun getLotDetailsByDoPickOrderRecordId(@PathVariable doPickOrderRecordId: Long): LotDetailsByDoPickOrderRecordResponse {
        return pickOrderService.getLotDetailsByDoPickOrderRecordId3(doPickOrderRecordId)
    }

    @PostMapping("/groups")
    fun createGroup(@RequestBody request: Map<String, Any>): ResponseEntity<Map<String, Any>> {
        println("request: $request")
        val name = request["name"] as String
        val targetDateStr = request["targetDate"] as String
        val targetDate = LocalDate.parse(targetDateStr)
        val pickOrderId = when (val value = request["pickOrderId"]) {
            is Int -> value.toLong()
            is Long -> value
            is String -> value.toLongOrNull()
            else -> null
        }
        println("name: $name")
        println("targetDate: $targetDate")
        println("pickOrderId: $pickOrderId")
        val group = pickOrderService.createGroup(name, targetDate, pickOrderId)
        return ResponseEntity.ok(
            mapOf(
                "id" to (group.id ?: 0L),
                "name" to (group.name ?: ""),
                "targetDate" to (group.targetDate?.toString() ?: ""),
                "pickOrderId" to (group.pickOrderId ?: 0L)
            )
        )
        //println("Response: $response")
    }

    @GetMapping("/groups/{pickOrderId}")
    fun getGroupsByPickOrder(@PathVariable pickOrderId: Long): ResponseEntity<List<Map<String, Any>>> {
        val groups = pickOrderService.getGroupsByPickOrderId(pickOrderId)
        val response = groups.map { group ->
            mapOf(
                "id" to (group.id ?: 0L),
                "name" to (group.name ?: ""),
                "targetDate" to (group.targetDate?.toString() ?: ""),
                "pickOrderId" to (group.pickOrderId ?: 0L)
            )
        }
        return ResponseEntity.ok(response)


    }

    @GetMapping("/groups/latest")
    fun getLatestGroupName(): MessageResponse {
        return pickOrderService.getLatestGroupNameAndCreate()
    }

    @GetMapping("/groups/list")
    fun getAllGroups(): List<PickOrderGroupInfo> {
        return pickOrderService.allPickOrdersGroup()
    }

    @PostMapping("/groups/create")
    fun createNewGroups(@Valid @RequestBody request: SavePickOrderGroupRequest): MessageResponse {
        return pickOrderService.createNewGroups(request)
    }


    @GetMapping("/detail-optimized/{userId}")
    fun getPickOrderDetailsOptimizedByUser(@PathVariable userId: Long): GetPickOrderInfoResponse {
        return pickOrderService.getPickOrderDetailsOptimizedByUser(userId)
    }

    @PostMapping("/auto-assign-release/{userId}")
    fun autoAssignAndReleasePickOrder(@PathVariable userId: Long): MessageResponse {
        return pickOrderService.autoAssignAndReleasePickOrder(userId)
    }
    /* 
    @PostMapping("/auto-assign-release-by-store")
    fun autoAssignReleaseByStore(
        @RequestParam userId: Long,
        @RequestParam storeId: String
    ): MessageResponse {
        return pickOrderService.autoAssignAndReleasePickOrderByStore(userId, storeId)
    }
    */
    @GetMapping("/check-pick-completion/{userId}")
    fun checkPickOrderCompletion(@PathVariable userId: Long): MessageResponse {
        return pickOrderService.checkPickOrderCompletion(userId)
    }

    @PostMapping("/check-complete/{consoCode}")
    fun checkAndCompletePickOrderByConsoCode(@PathVariable consoCode: String): MessageResponse {
        return pickOrderService.checkAndCompletePickOrderByConsoCode(consoCode)
    }

    @GetMapping("/all-lots-with-details/{userId}")
    fun getAllPickOrderLotsWithDetails(@PathVariable userId: Long): List<Map<String, Any?>> {
        return pickOrderService.getAllPickOrderLotsWithDetailsWithAutoAssign(userId)
    }

    @GetMapping("/fg-pick-orders")
    fun getFgPickOrders(): List<Map<String, Any?>> {
        return pickOrderService.getFgPickOrders()
    }
    @GetMapping("/fg-pick-orders/{userId}")
    fun getFgPickOrdersByUserId(@PathVariable userId: Long): List<Map<String, Any?>> {
        return pickOrderService.getFgPickOrdersByUserId(userId)
    }

    @GetMapping("/all-lots-with-details-no-auto-assign/{userId}")
    fun getAllPickOrderLotsWithDetailsWithoutAutoAssign(@PathVariable userId: Long): List<Map<String, Any>> {
        return pickOrderService.getAllPickOrderLotsWithDetailsWithoutAutoAssign(userId)
    }
    @GetMapping("/all-lots-hierarchical/{userId}")
    fun getAllPickOrderLotsHierarchical(@PathVariable userId: Long): Map<String, Any?> {
        return pickOrderService.getAllPickOrderLotsWithDetailsHierarchical(userId)
    }

    @GetMapping("/fg-pick-orders-workbench/{userId}")
    fun getFgPickOrdersByUserIdWorkbench(@PathVariable userId: Long): List<Map<String, Any?>> {
        return doWorkbenchMainService.getFgPickOrdersByUserIdWorkbench(userId)
    }

    @GetMapping("/all-lots-hierarchical-workbench/{userId}")
    fun getAllPickOrderLotsHierarchicalWorkbench(@PathVariable userId: Long): Map<String, Any?> {
        return doWorkbenchMainService.getAllPickOrderLotsWithDetailsHierarchicalWorkbench(userId)
    }
/* @PostMapping("/auto-assign-release-by-ticket")
fun autoAssignAndReleasePickOrderByTicket(
    @RequestParam storeId: String,
    @RequestParam ticketNo: String,
    @RequestParam userId: Long
): MessageResponse {
    return pickOrderService.autoAssignAndReleasePickOrderByStoreAndTicket(storeId, ticketNo, userId)
}
*/
@GetMapping("/orders-by-store/{storeId}")
fun getPickOrdersByStore(@PathVariable storeId: String): Map<String, Any?> {
    return pickOrderService.getPickOrdersByDateAndStore(storeId)
}
@PostMapping("/lot-substitution/confirm")
fun confirmLotSubstitution(@RequestBody req: LotSubstitutionConfirmRequest): MessageResponse {
    return pickOrderService.confirmLotSubstitution(req)
}

@GetMapping("/completed-do-pick-orders/{userId}")
fun getCompletedDoPickOrders(
    @PathVariable userId: Long,
    @RequestParam(required = false) shopName: String?,
    @RequestParam(required = false) targetDate: String?,
    @RequestParam(required = false) deliveryNoteCode: String?,
    @RequestParam(required = false) truckLanceCode: String?,
): List<CompletedDoPickOrderResponse> {
    val request = GetCompletedDoPickOrdersRequest(
        targetDate = targetDate,
        shopName = shopName,
        deliveryNoteCode = deliveryNoteCode,
        truckLanceCode = truckLanceCode,
    )
    return pickOrderService.getCompletedDoPickOrders(userId, request)
}

@GetMapping("/completed-do-pick-orders-workbench/{userId}")
fun getCompletedDoPickOrdersWorkbench(
    @PathVariable userId: Long,
    @RequestParam(required = false) shopName: String?,
    @RequestParam(required = false) targetDate: String?,
    @RequestParam(required = false) deliveryNoteCode: String?,
    @RequestParam(required = false) truckLanceCode: String?,
    @RequestParam(required = false) ticketNo: String?,
): List<CompletedDoPickOrderResponse> {
    val request = GetCompletedDoPickOrdersRequest(
        targetDate = targetDate,
        shopName = shopName,
        deliveryNoteCode = deliveryNoteCode,
        truckLanceCode = truckLanceCode,
        ticketNo = ticketNo,
    )
    return doWorkbenchMainService.getCompletedDoPickOrdersWorkbench(userId, request)
}

@GetMapping("/completed-do-pick-orders-workbench-all")
fun getCompletedDoPickOrdersWorkbenchAll(
    @RequestParam(required = false) shopName: String?,
    @RequestParam(required = false) targetDate: String?,
    @RequestParam(required = false) deliveryNoteCode: String?,
    @RequestParam(required = false) truckLanceCode: String?,
    @RequestParam(required = false) ticketNo: String?,
): List<CompletedDoPickOrderResponse> {
    val request = GetCompletedDoPickOrdersRequest(
        targetDate = targetDate,
        shopName = shopName,
        deliveryNoteCode = deliveryNoteCode,
        truckLanceCode = truckLanceCode,
        ticketNo = ticketNo,
    )
    return doWorkbenchMainService.getCompletedDoPickOrdersWorkbenchAll(request)
}

@GetMapping("/completed-do-pick-orders-all")
fun getCompletedDoPickOrdersAll(
    @RequestParam(required = false) shopName: String?,
    @RequestParam(required = false) targetDate: String?,
    @RequestParam(required = false) deliveryNoteCode: String?,
    @RequestParam(required = false) truckLanceCode: String?,
): List<CompletedDoPickOrderResponse> {
    val request = GetCompletedDoPickOrdersRequest(
        targetDate = targetDate,
        shopName = shopName,
        deliveryNoteCode = deliveryNoteCode,
        truckLanceCode = truckLanceCode,
    )
    return pickOrderService.getCompletedDoPickOrdersAll(request)
}


}