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

import com.ffii.fpsms.modules.jobOrder.service.PlasticBagPrinterService
import com.ffii.fpsms.modules.jobOrder.service.PSService
import com.ffii.fpsms.modules.jobOrder.web.model.PrintRequest
import com.ffii.fpsms.modules.jobOrder.web.model.LaserRequest
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.*
import java.time.LocalDate
import java.time.format.DateTimeParseException
import org.springframework.http.ResponseEntity

@RestController
@RequestMapping("/ps")
class PSController(
    private val psService: PSService,
) {
    /**
     * Bulk import fake on-hand overrides from Excel.
     * Replaces the entire item_fake_onhand table with the provided rows.
     * Expected body: [{ "itemCode": "...", "onHandQty": 123.45 }, ...]
     */
    @PostMapping("/importFakeOnHand")
    fun importFakeOnHand(@RequestBody rows: List<Map<String, Any?>>): ResponseEntity<Map<String, Any>> {
        psService.importFakeOnHand(rows)
        return ResponseEntity.ok(mapOf("ok" to true, "count" to rows.size))
    }

    @GetMapping("/search-ps")
    fun searchPs(@RequestParam produceAt: String): ResponseEntity<List<Map<String, Any>>> {
        // Returns fields: id, produceAt, totalEstProdCount, totalFGType
        val results = psService.searchProductionSchedules(produceAt)
        return ResponseEntity.ok(results)
    }

    @GetMapping("/search-ps-line")
    fun searchPsLine(@RequestParam psId: Int): ResponseEntity<List<Map<String, Any>>> {
        // Returns fields: id, itemCode, itemName, avgQtyLastMonth, stockQty, daysLeft, batchNeed, prodQty, itemPriority
        val results = psService.getProductionScheduleLines(psId)
        return ResponseEntity.ok(results)
    }

    /** 每日平均出貨量: itemCode, itemName, avgQtyLastMonth, dailyQty, isCoffee, isTea, isLemon. Default: 6 days before today to 1 day after today. */
    @GetMapping("/itemDailyOut.json")
    fun itemDailyOut(
        @RequestParam(required = false) fromDate: String?,
        @RequestParam(required = false) toDate: String?,
    ): ResponseEntity<List<Map<String, Any>>> {
        val defaultToday = LocalDate.now()
        val to = toDate?.let { LocalDate.parse(it) } ?: defaultToday.plusDays(1)
        val from = fromDate?.let { LocalDate.parse(it) } ?: defaultToday.minusDays(6)
        val results = psService.getItemDailyOut(from, to)
        return ResponseEntity.ok(results)
    }

    /** Set daily out qty for an item (update or insert). */
    @PostMapping("/setDailyQtyOut")
    fun setDailyQtyOut(@RequestBody body: Map<String, Any>): ResponseEntity<Map<String, Any>> {
        val itemCode = body["itemCode"]?.toString() ?: return ResponseEntity.badRequest().body(mapOf("error" to "itemCode required"))
        val dailyQty = (body["dailyQty"] as? Number) ?: (body["dailyQty"]?.toString()?.toDoubleOrNull() ?: 0)
        psService.setDailyQtyOut(itemCode, dailyQty)
        return ResponseEntity.ok(mapOf("ok" to true, "itemCode" to itemCode, "dailyQty" to dailyQty))
    }

    /** Clear daily out qty for an item (delete from item_daily_out). */
    @PostMapping("/clearDailyQtyOut")
    fun clearDailyQtyOut(@RequestBody body: Map<String, Any>): ResponseEntity<Map<String, Any>> {
        val itemCode = body["itemCode"]?.toString() ?: return ResponseEntity.badRequest().body(mapOf("error" to "itemCode required"))
        psService.clearDailyQtyOut(itemCode)
        return ResponseEntity.ok(mapOf("ok" to true, "itemCode" to itemCode))
    }

    /** Set or clear fake onhand for an item. onHandQty: number to set, or omit/null to delete. */
    @PostMapping("/setFakeOnHand")
    fun setFakeOnHand(@RequestBody body: Map<String, Any>): ResponseEntity<Map<String, Any>> {
        val itemCode = body["itemCode"]?.toString() ?: return ResponseEntity.badRequest().body(mapOf("error" to "itemCode required"))
        val onHandQty = body["onHandQty"]?.let { (it as? Number) ?: (it.toString().toDoubleOrNull()) }
        psService.setFakeOnHand(itemCode, onHandQty)
        return ResponseEntity.ok(mapOf("ok" to true, "itemCode" to itemCode, "onHandQty" to (onHandQty ?: "deleted")))
    }

    /** Recalculate inventory on-hand from lot lines for FG BOM items (排期設定 刷新庫存). */
    @PostMapping("/refresh-inventory-onhand")
    fun refreshInventoryOnHand(): ResponseEntity<Map<String, Any>> {
        val updated = psService.refreshInventoryOnHandForFgBomItems()
        return ResponseEntity.ok(mapOf("ok" to true, "updated" to updated))
    }

    /** Set or clear coffee/tea/lemon for an item. systemType: coffee | tea | lemon, enabled: boolean. */
    @PostMapping("/setCoffeeOrTea")
    fun setCoffeeOrTea(@RequestBody body: Map<String, Any>): ResponseEntity<Map<String, Any>> {
        val itemCode = body["itemCode"]?.toString() ?: return ResponseEntity.badRequest().body(mapOf("error" to "itemCode required"))
        val systemType = body["systemType"]?.toString() ?: return ResponseEntity.badRequest().body(mapOf("error" to "systemType required"))
        if (systemType !in listOf("coffee", "tea", "lemon")) {
            return ResponseEntity.badRequest().body(mapOf("error" to "systemType must be coffee, tea, or lemon"))
        }
        val enabled = body["enabled"] == true
        psService.setCoffeeOrTea(itemCode, systemType, enabled)
        return ResponseEntity.ok(mapOf("ok" to true, "itemCode" to itemCode, "systemType" to systemType, "enabled" to enabled))
    }

    /**
     * Export delivery-order qty sums (stock unit) for BOM items, pivoted by ETA date.
     */
    @GetMapping(
        value = ["/export-do-qty-by-date"],
        produces = ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],
    )
    fun exportDoQtyByDate(
        @RequestParam fromDate: String,
        @RequestParam toDate: String,
    ): ResponseEntity<Any> {
        val from = try {
            LocalDate.parse(fromDate)
        } catch (_: DateTimeParseException) {
            return ResponseEntity.badRequest().body(mapOf("error" to "Invalid fromDate"))
        }
        val to = try {
            LocalDate.parse(toDate)
        } catch (_: DateTimeParseException) {
            return ResponseEntity.badRequest().body(mapOf("error" to "Invalid toDate"))
        }
        return try {
            val bytes = psService.exportDeliveryOrderQtyByDateExcel(from, to)
            val filename = "do_qty_${from}_to_${to}.xlsx"
            ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=$filename")
                .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                .body(bytes)
        } catch (e: IllegalArgumentException) {
            ResponseEntity.badRequest().body(mapOf("error" to (e.message ?: "Invalid date range")))
        }
    }
}