package com.ffii.fpsms.modules.productProcess.web

import com.ffii.fpsms.modules.productProcess.entity.ProductProcess
import com.ffii.fpsms.modules.productProcess.entity.ProductProcessLine
import com.ffii.fpsms.modules.productProcess.enums.ProductProcessStatus
import com.ffii.fpsms.modules.productProcess.service.ProductProcessService
import com.ffii.fpsms.modules.productProcess.web.model.*
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.web.bind.annotation.*
import com.ffii.fpsms.modules.productProcess.entity.projections.ProductProcessInfo
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import java.time.LocalDate
import java.time.format.DateTimeFormatter

@RestController
@RequestMapping("/product-process")
class ProductProcessController(
    private val productProcessService: ProductProcessService
) {

    @GetMapping
    fun findAll(pageable: Pageable): Page<ProductProcessSimpleResponse> {  //  改为返回 DTO
        println("📋 Controller: GET /product-process - Finding all")
        val result = productProcessService.findAllAsDto(pageable)  //  使用新方法
        println(" Controller: Returning ${result.totalElements} records")
        return result
    }

    @GetMapping("/{id}")
    fun findById(@PathVariable id: Long): ProductProcessSimpleResponse {  //  改为返回 DTO
        println("    Controller: GET /product-process/$id")
        val result = productProcessService.findByIdAsDto(id)  //  使用新方法
        println(" Controller: Found: ${result.productProcessCode}")
        return result
    }

    @GetMapping("/code/{code}")
    fun findByCode(@PathVariable code: String): ProductProcess {
        println("    Controller: GET /product-process/code/$code")
        val result = productProcessService.findByCode(code)
        println(" Controller: Found ID: ${result.id}")
        return result
    }

    @PostMapping
    fun create(@RequestBody request: SaveProductProcessRequest): SaveProductProcessResponse {
        println("💾 Controller: POST /product-process - Creating ProductProcess")
        //println("📦 Controller: Request - bomId: ${request.bomId}, jobOrderId: ${request.jobOrderId}, date: ${request.date}")  //  修复
        val result = productProcessService.create(request)
        println(" Controller: Created ProductProcess - ID: ${result.id}, Code: ${result.productProcessCode}, Lines: ${result.linesCreated}")  //  改进日志
        return result
    }

    @PostMapping("/{id}/start")
    fun startProcess(@PathVariable id: Long, @RequestParam operatorId: Long): ProductProcessSimpleResponse {
        println("▶️ Controller: POST /product-process/$id/start - operatorId: $operatorId")
        val result = productProcessService.startProcessAsDto(id, operatorId)  //  改用 AsDto 方法
        println(" Controller: Process started")
        return result
    }

    @PostMapping("/{id}/stop")
    fun stopProcess(
        @PathVariable id: Long,
        @RequestBody request: StopProcessRequest
    ): ProductionProcessIssueResponse {  //  改为 Issue Response
        println("⏸️ Controller: POST /product-process/$id/stop")
        println("📦 Controller: Reason: ${request.reason}")
        val result = productProcessService.stopProcessAsDto(id, request)  //  使用返回 DTO 的方法
        println(" Controller: Process stopped, issue ID: ${result.id}")
        return result
    }

    @PostMapping("/{id}/resume/{issueId}")
    fun resumeProcess(
        @PathVariable id: Long,
        @PathVariable issueId: Long
    ): ProductionProcessIssueResponse {  //  改为 Issue Response
        println("▶️ Controller: POST /product-process/$id/resume/$issueId")
        val result = productProcessService.resumeProcessAsDto(id, issueId)  //  使用返回 DTO 的方法
        println(" Controller: Process resumed, stop duration: ${result.totalTime} min")
        return result
    }

    @PostMapping("/{id}/complete")
    fun completeProcess(@PathVariable id: Long): ProductProcessSimpleResponse {
        println("✔️ Controller: POST /product-process/$id/complete")
        val result = productProcessService.completeProcessAsDto(id)  //  改用 AsDto 方法
        println(" Controller: Process completed")
        return result
    }

    @PostMapping("/{id}/lines")
    fun addLine(
        @PathVariable id: Long,
        @RequestBody request: SaveProductProcessLineRequest
    ): SaveProductProcessLineResponse {
        println("➕ Controller: POST /product-process/$id/lines")
        println("📦 Controller: Line - name: ${request.name}, equipment: ${request.equipmentType}")
        val result = productProcessService.addLine(id, request)
        println(" Controller: Line added with ID: ${result.id}")
        return result
    }

    @PutMapping("/lines/{lineId}/output")
    fun updateLineOutput(
        @PathVariable lineId: Long,
        @RequestBody request: UpdateLineOutputRequest
    ): ProductProcessLineResponse {  //  改为 ProductProcessLineResponse
        println("📊 Controller: PUT /lines/$lineId/output")
        val result = productProcessService.updateLineOutputAsDto(lineId, request)
        println(" Controller: Line output updated")
        return result
    }

    @GetMapping("/{id}/lines")
    fun getLines(@PathVariable id: Long): List<ProductProcessLineResponse> {
        println("📋 Controller: GET /product-process/$id/lines")
        val result = productProcessService.getLinesAsDto(id)
        println(" Controller: Found ${result.size} lines")
        return result
    }

    @GetMapping("/{id}/issues")
    fun getIssues(@PathVariable id: Long): List<ProductionProcessIssueResponse> {  //  改为 Issue Response List
        println("📋 Controller: GET /product-process/$id/issues")
        val result = productProcessService.getIssuesAsDto(id)  //  使用返回 DTO 的方法
        println(" Controller: Found ${result.size} issues")
        return result
    }

    @GetMapping("/by-job-order/{jobOrderId}")
    fun findByJobOrderId(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> {  //  改为返回 DTO
        println("    Controller: GET /product-process/by-job-order/$jobOrderId")
        val result = productProcessService.findByJobOrderIdWithLines(jobOrderId)  //  直接使用 with-lines 方法
        println(" Controller: Found ${result.size} processes for Job Order $jobOrderId")
        return result
    }

    //  额外添加：获取带 lines 的完整数据
    @GetMapping("/by-job-order/{jobOrderId}/with-lines")
    fun findByJobOrderIdWithLines(@PathVariable jobOrderId: Long): List<ProductProcessWithLinesResponse> {
        println("    Controller: GET /product-process/by-job-order/$jobOrderId/with-lines")
        val result = productProcessService.findByJobOrderIdWithLines(jobOrderId)
        println(" Controller: Found ${result.size} processes with lines for Job Order $jobOrderId")
        return result
    }

    @PostMapping("/lines/{lineId}/start")
    fun startLine(@PathVariable lineId: Long, @RequestParam userId: Long): ProductProcessLineResponse {
        println("▶️ Controller: POST /product-process/lines/$lineId/start - userId: $userId")
        val entity = productProcessService.startLine(lineId, userId)
        //  修复：返回正确的 DTO
        return productProcessService.getLinesAsDto(entity.productProcess?.id!!).find { it.id == entity.id!! }!!
    }
/*
    @GetMapping("/demo/{id}")
    fun demo(@PathVariable id: Long): ProductProcessInfo {
        return productProcessService.productProcessDetailfindbyidtest(id)
    }
    */
    @GetMapping("/demo/joid/{joid}")
    fun demojoid(@PathVariable joid: Long): List<ProductProcessInfo> {
        return productProcessService.productProcessDetailfindbyjoid(joid)
    }
    @PostMapping("/demo/joid/{joid}/{productionPriority}")
    fun democreate(@PathVariable joid: Long, @PathVariable productionPriority: Int): MessageResponse {
        return productProcessService.createProductProcessByJobOrderId(joid, productionPriority)
    }
    @PostMapping("/Demo/update")
    fun demoupdate(@RequestBody request: UpdateProductProcessLineOperatorIdOrEquipmentIdRequest): MessageResponse {
        return productProcessService.UpdateProductProcessLineOperatorIdOrEquipmentId(request)
    }
    @PostMapping("/Demo/NewUpdate")
    fun demoNewUpdate(@RequestBody request: NewUpdateProductProcessLineOperatorIdOrEquipmentIdAndEquipmentDetailRequest): MessageResponse {
        return productProcessService.NewUpdateProductProcessLineOperatorIdOrEquipmentIdAndEquipmentDetail(request)
    }
    @PostMapping("/Demo/update/handler")
    fun demoupdatehandler(@RequestBody request: UpdateProductProcessLineHandlerIdRequest): MessageResponse {
        return productProcessService.UpdateProductProcessLineHandlerId(request)
    }
    @PostMapping("/Demo/ProcessLine/update/status")
    fun demoupdatestatus(@RequestBody request: UpdateProductProcessLineStatusRequest): MessageResponse {
        return productProcessService.updateProductProcessLineStatus(request.productProcessLineId, request.status)
    }
    @GetMapping("/Demo/ProcessLine/detail/{lineId}")
    fun demoprocesslinedetail(@PathVariable lineId: Long): JobOrderProcessLineDetailResponse {
        return productProcessService.getJobOrderProcessLineDetail(lineId)
    }
    @PostMapping("/Demo/ProcessLine/update/qty/{lineId}")
    fun demoupdateqty(@PathVariable lineId: Long, @RequestBody request: UpdateProductProcessLineQtyRequest): MessageResponse {
        return productProcessService.updateProductProcessLineQty(request)
    }
    
    @GetMapping("/Demo/Process/all")
    fun demoprocessall(
        @RequestParam(name = "type", required = false) bomType: String?
    ): List<AllJoborderProductProcessInfoResponse> {
        return productProcessService.getAllJoborderProductProcessInfo(bomType)
    }

    @GetMapping("/Demo/Process/search")
    fun demoprocesssearch(
        @RequestParam(required = false) date: String?,
        @RequestParam(required = false) itemCode: String?,
        @RequestParam(required = false) jobOrderCode: String?,
        @RequestParam(required = false) bomIds: String?,
        @RequestParam(required = false) qcReady: Boolean?,
        @RequestParam(required = false) includePutaway: Boolean?, 
        /** all | completed | notCompleted */
        @RequestParam(required = false) putawayStatus: String?,
        @RequestParam(name = "type", required = false) bomType: String?,
        @RequestParam(defaultValue = "0") page: Int,
        @RequestParam(defaultValue = "50") size: Int
    ): JobOrderProductProcessPageResponse {
        val parsedDate = date?.takeIf { it.isNotBlank() }?.let {
            LocalDate.parse(it, DateTimeFormatter.ISO_DATE)
        }

        val parsedBomIds: List<Long>? = bomIds
            ?.takeIf { it.isNotBlank() }
            ?.split(",")
            ?.mapNotNull { token -> token.trim().toLongOrNull() }

        return productProcessService.searchJoborderProductProcessesPaged(
            date = parsedDate,
            itemCode = itemCode,
            jobOrderCode = jobOrderCode,
            bomIds = parsedBomIds,
            qcReady = qcReady,
            includePutaway = includePutaway,
            putawayStatus = putawayStatus,
            bomType = bomType,
            page = page,
            size = size
        )
    }

    /** Nav: QC vs 上架 reminders (今日／昨日產程、等同完成QC工單列表資格). */
    @GetMapping("/Demo/Process/alerts/fg-qc-putaway")
    fun getFgQcPutAwayAlerts(): JobOrderFgAlertsResponse =
        productProcessService.findJobOrderFgQcAndPutAwayAlertsForTodayYesterday()

    @PostMapping("/Demo/ProcessLine/start/{lineId}")
    fun startProductProcessLine(@PathVariable lineId: Long): MessageResponse {
        return productProcessService.StartProductProcessLine(lineId)
    }
    @PostMapping("/Demo/ProcessLine/complete/{lineId}")
    fun completeProductProcessLine(@PathVariable lineId: Long): MessageResponse {
        return productProcessService.CompleteProductProcessLine(lineId)
    }
    @PostMapping("/Demo/ProcessLine/issue")
    fun issueProductProcessLine(@RequestBody request: SaveProductProcessIssueTimeRequest): MessageResponse {
        return productProcessService.SaveProductProcessIssueTime(request)
    }
    @PostMapping("/Demo/ProcessLine/resume/{productProcessIssueId}")
    fun resumeProductProcessLine(@PathVariable productProcessIssueId: Long): MessageResponse {
        return productProcessService.SaveProductProcessResumeTime(productProcessIssueId)
    }
    @PostMapping("/Demo/Process/update/priority/{productProcessId}/{productionPriority}")
    fun updateProductProcessPriority(@PathVariable productProcessId: Long, @PathVariable productionPriority: Int): MessageResponse {
        return productProcessService.UpdateProductProcessPriority(productProcessId, productionPriority)
    }
    @PostMapping("/Demo/ProcessLine/pass/{lineId}")
    fun passProductProcessLine(@PathVariable lineId: Long): MessageResponse {
        return productProcessService.passProductProcessLine(lineId)
    }
    @PostMapping("/Demo/ProcessLine/new/{lineId}")
    fun newProductProcessLine(@PathVariable lineId: Long): MessageResponse {
        return productProcessService.createNewProductProcessLine(lineId)
    }
    @PostMapping("/Demo/ProcessLine/update/processingTimeSetupTimeChangeoverTime/{lineId}")
    fun updateProductProcessLineProcessingTimeSetupTimeChangeoverTime(@PathVariable lineId: Long, @RequestBody request: UpdateProductProcessLineProcessingTimeSetupTimeChangeoverTimeRequest): MessageResponse {
        return productProcessService.UpdateProductProcessLineProcessingTimeSetupTimeChangeoverTime(request)
    }
    @GetMapping("/Demo/JobProcessStatus")
    fun getJobProcessStatus(
        @RequestParam(required = false) date: String?,
        @RequestParam(required = false) productProcessStatus: String?
    ): List<JobProcessStatusResponse> {
        val parsedDate = date?.takeIf { it.isNotBlank() }?.let {
            LocalDate.parse(it, DateTimeFormatter.ISO_DATE) // yyyy-MM-dd
        }
        val statusFilter = productProcessStatus?.takeIf { it.isNotBlank() }?.let { raw ->
            ProductProcessStatus.values().find { it.value.equals(raw, ignoreCase = true) }
        }
        return productProcessService.getJobProcessStatus(parsedDate, statusFilter)
    }
    @PostMapping("/Demo/ProcessLine/delete/{lineId}")
    fun deleteProductProcessLine(@PathVariable lineId: Long): MessageResponse {
        return productProcessService.deleteProductProcessLine(lineId)
    }

    // ===== Dashboards =====

    @GetMapping("/Demo/OperatorKpi")
    fun getOperatorKpi(@RequestParam(required = false) date: String?): List<OperatorKpiResponse> {
        val parsedDate = date?.takeIf { it.isNotBlank() }?.let {
            LocalDate.parse(it, DateTimeFormatter.ISO_DATE)
        }
        return productProcessService.getOperatorKpi(parsedDate)
    }

    @GetMapping("/Demo/EquipmentStatus")
    fun getEquipmentStatus(): List<EquipmentStatusByTypeResponse> {
        return productProcessService.getEquipmentStatusByType()
    }

    /** FP-MTMS Version Checklist | Functions Ref. No. 27 | v1.0.0 | 2026-07-20 */
    @GetMapping("/Demo/DrinkProductionQty")
    fun getDrinkProductionQty(@RequestParam(required = false) date: String?): List<DrinkProductionQtyResponse> {
        val parsedDate = date?.takeIf { it.isNotBlank() }?.let {
            LocalDate.parse(it, DateTimeFormatter.ISO_DATE)
        }
        return productProcessService.getDrinkProductionQty(parsedDate)
    }
}