package com.ffii.fpsms.modules.jobOrder.web

import com.ffii.core.response.RecordsRes
import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderDetail
import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfo
import com.ffii.fpsms.modules.jobOrder.service.JobOrderBomMaterialService
import com.ffii.fpsms.modules.jobOrder.service.JobOrderProcessService
import com.ffii.fpsms.modules.jobOrder.service.JobOrderService
import com.ffii.fpsms.modules.jobOrder.web.model.CreateJobOrderRequest
import com.ffii.fpsms.modules.jobOrder.web.model.JobOrderCommonActionRequest
import com.ffii.fpsms.modules.jobOrder.web.model.SearchJobOrderInfoRequest
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import jakarta.validation.Valid
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.RestController
import com.ffii.fpsms.modules.jobOrder.service.JoPickOrderService
import com.ffii.fpsms.modules.jobOrder.web.model.*
import com.ffii.fpsms.modules.jobOrder.web.model.ExportPickRecordRequest
import com.ffii.fpsms.modules.jobOrder.web.model.PrintPickRecordRequest
import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanSubmitRequest
import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanIssueRequest
import jakarta.servlet.http.HttpServletResponse
import net.sf.jasperreports.engine.JasperExportManager
import net.sf.jasperreports.engine.JasperPrint
import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException
import org.springframework.context.NoSuchMessageException
import java.io.OutputStream
import java.io.UnsupportedEncodingException
import java.text.ParseException
import org.springframework.web.bind.annotation.*  
import org.springframework.web.bind.annotation.RequestParam 
@RestController
@RequestMapping("/jo")
class JobOrderController(
    private val jobOrderService: JobOrderService,
    private val jobOrderBomMaterialService: JobOrderBomMaterialService,
    private val jobOrderProcessService: JobOrderProcessService,
    private val joPickOrderService: JoPickOrderService
) {

    @GetMapping("/getRecordByPage")
    fun allJobOrdersByPage(@ModelAttribute request: SearchJobOrderInfoRequest): RecordsRes<JobOrderInfo> {
        return jobOrderService.allJobOrdersByPage(request);
    }

    @GetMapping("/detail/{id}")
    fun jobOrderDetail(@PathVariable id: Long): JobOrderDetail {
        return jobOrderService.jobOrderDetail(id);
    }

    @GetMapping("/detailByCode/{code}")
    fun jobOrderDetailByCode(@PathVariable code: String): JobOrderDetail {
        return jobOrderService.jobOrderDetailByCode(code);
    }

    @PostMapping("/update")
    fun updateJobOrder(@Valid @RequestBody request: JobOrderUpdateRequest): MessageResponse {
        return jobOrderService.updateJobOrder(request)
    }

    @PostMapping("/release")
    fun releaseJobOrder(@Valid @RequestBody request: JobOrderCommonActionRequest): MessageResponse {
        return jobOrderService.releaseJobOrder(request)
    }

    @PostMapping("/start")
    fun startJobOrder(@Valid @RequestBody request: JobOrderCommonActionRequest): MessageResponse {
        val jo = jobOrderService.startJobOrder(request)
        if (jo.id == null) {
            throw NoSuchElementException()
        }
        jobOrderBomMaterialService.completeJobOrderBomMaterialsByJoId(jo.id)

        return jo
    }

    @PostMapping("/manualCreate")
    fun manualCreateJobOrder(@Valid @RequestBody request: CreateJobOrderRequest): MessageResponse {
        val jo = jobOrderService.createJobOrder(request)
        if (jo.id == null) {
            throw NoSuchElementException()
        }
        jobOrderBomMaterialService.createJobOrderBomMaterialsByJoId(jo.id)
        jobOrderProcessService.createJobOrderProcessesByJoId(jo.id)

        return jo
    }
    @GetMapping("/all-lots-hierarchical/{userId}")
    fun getAllJobOrderLotsHierarchical(@PathVariable userId: Long): Map<String, Any?> {
        return joPickOrderService.getAllJobOrderLotsWithDetailsHierarchical(userId)
    }

    @GetMapping("/completed-job-order-pick-orders/{userId}")
    fun getCompletedJobOrderLotsHierarchical(@PathVariable userId: Long): Map<String, Any?> {
        return joPickOrderService.getCompletedJobOrderLotsHierarchical(userId)
    }

    @GetMapping("/completed-job-order-pick-order-records/{userId}")
    fun getCompletedJobOrderPickOrderRecords(@PathVariable userId: Long): List<Map<String, Any?>> {
        return joPickOrderService.getCompletedJobOrderPickOrderRecords(userId)
    }
    @GetMapping("/unassigned-job-order-pick-orders")
    fun getUnassignedJobOrderPickOrders(): List<Map<String, Any?>> {
        return joPickOrderService.getUnassignedJobOrderPickOrders()
    }

    @PostMapping("/assign-job-order-pick-order/{pickOrderId}/{userId}")
    fun assignJobOrderPickOrderToUser(
        @PathVariable pickOrderId: Long,
        @PathVariable userId: Long
    ): MessageResponse {
        return joPickOrderService.assignJobOrderPickOrderToUser(pickOrderId, userId)
    }

    @PostMapping("/update-match-status")
    fun updateMatchStatus(@RequestBody request: UpdateMatchStatusRequest): MessageResponse {
        return joPickOrderService.updateMatchStatus(
            request.pickOrderId, 
            request.itemId, 
            request.userId, 
            request.qty
        )
    }

    @PostMapping("/second-scan-submit/{pickOrderId}/{itemId}")
    fun submitSecondScanQuantity(
        @PathVariable pickOrderId: Long,
        @PathVariable itemId: Long,
        @RequestBody data: Map<String, Any>
    ): MessageResponse {
        val request = SecondScanSubmitRequest(
            pickOrderId = pickOrderId, // ✅ Use path variable
            itemId = itemId, // ✅ Use path variable
            qty = (data["qty"] as Number).toDouble(),
            isMissing = data["isMissing"] as? Boolean ?: false,
            isBad = data["isBad"] as? Boolean ?: false
        )
        return joPickOrderService.submitSecondScanQty(request)
    }
    
    @PostMapping("/second-scan-issue/{pickOrderId}/{itemId}")
fun recordSecondScanIssue(
    @PathVariable pickOrderId: Long,
    @PathVariable itemId: Long,
    @RequestBody data: Map<String, Any>
): MessageResponse {
    val request = SecondScanIssueRequest(
        pickOrderId = pickOrderId, // ✅ path 变量
        itemId = itemId,           // ✅ path 变量
        qty = (data["qty"] as Number).toDouble(),
        // ✅ 新增：安全读取 missQty/badItemQty/type，默认 0/"match"
        missQty = (data["missQty"] as? Number)?.toDouble() ?: 0.0,
        badItemQty = (data["badItemQty"] as? Number)?.toDouble() ?: 0.0,
        isMissing = data["isMissing"] as? Boolean ?: false,
        isBad = data["isBad"] as? Boolean ?: false,
        reason = data["reason"] as? String ?: "",
        createdBy = (data["createdBy"] as Number).toLong(),
        type = (data["type"] as? String) ?: "match"
    )
    return joPickOrderService.recordSecondScanIssue(request)
}
    @GetMapping("/completed-job-order-pick-orders-with-completed-second-scan/{userId}")
    fun getCompletedJobOrderPickOrdersWithCompletedSecondScan(@PathVariable userId: Long): List<Map<String, Any?>> {
        return joPickOrderService.getCompletedJobOrderPickOrdersWithCompletedSecondScan(userId)
    }
    @GetMapping("/completed-job-order-pick-order-lot-details/{pickOrderId}")
    fun getCompletedJobOrderPickOrderLotDetails(@PathVariable pickOrderId: Long): List<Map<String, Any?>> {
        return joPickOrderService.getCompletedJobOrderPickOrderLotDetails(pickOrderId)
    }

    @PostMapping("/PickRecord")
    @Throws(UnsupportedEncodingException::class, NoSuchMessageException::class, ParseException::class, Exception::class)
    fun printPickRecord(@Valid @RequestBody request: ExportPickRecordRequest, response: HttpServletResponse){
        response.characterEncoding = "utf-8"
        response.contentType = "application/pdf"
        val out: OutputStream = response.outputStream
        val pdf = jobOrderService.exportPickRecord(request)
        val jasperPrint = pdf["report"] as JasperPrint
        response.addHeader("filename", "${pdf["filename"]}.pdf")
        out.write(JasperExportManager.exportReportToPdf(jasperPrint))
    }

    @GetMapping("/print-PickRecord")
    fun printPickRecord(@ModelAttribute request: PrintPickRecordRequest){
        jobOrderService.printPickRecord(request)
    }

    @GetMapping("/completed-job-order-pick-orders-only/{userId}")
    fun getCompletedJobOrderPickOrders(@PathVariable userId: Long): List<Map<String, Any?>> {
        return joPickOrderService.getCompletedJobOrderPickOrders(userId)
    }

    @GetMapping("/completed-job-order-pick-order-lot-details-completed-pick/{pickOrderId}")
    fun getCompletedJobOrderPickOrderLotDetailsForCompletedPick(@PathVariable pickOrderId: Long): List<Map<String, Any?>> {
        return joPickOrderService.getCompletedJobOrderPickOrderLotDetailsForCompletedPick(pickOrderId)
    }
}
