package com.ffii.fpsms.modules.master.web

import com.ffii.core.exception.NotFoundException
import com.ffii.core.response.RecordsRes
import com.ffii.core.utils.CriteriaArgsBuilder
import com.ffii.core.utils.PagingUtils
import com.ffii.fpsms.modules.master.entity.Items
import com.ffii.fpsms.modules.master.service.ItemsService
import com.ffii.fpsms.modules.master.web.models.ItemWithQcResponse
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import com.ffii.fpsms.modules.master.web.models.NewItemRequest
import jakarta.servlet.http.HttpServletRequest
import jakarta.validation.Valid
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import java.util.Collections.emptyList
import org.slf4j.Logger
import org.slf4j.LoggerFactory

@RestController
@RequestMapping("/items")
class ItemsController(
    private val itemsService: ItemsService
) {
    private val logger: Logger = LoggerFactory.getLogger(ItemsController::class.java)

    @GetMapping
    fun allItems(): List<Items> {
        return itemsService.allItems()
    }

    @GetMapping("/consumables")
    fun allConsumables(): List<Map<String, Any>> {
        return itemsService.allConsumables()
    }
//    @GetMapping("/getRecordByPage")
//    fun getAllItemsByPage(@RequestBody filterRequest: HttpServletRequest): RecordsRes<Map<String, Any>> {
//        val pageSize = filterRequest.getParameter("pageSize").toString().toInt(); // Default to 10 if not provided
//        val pageNumber = filterRequest.getParameter("pageNum").toString().toInt(); // Default to 0 if not provided
//        val criteriaArgs = CriteriaArgsBuilder.withRequest(filterRequest)
//            .addStringLike("name")
//            .build();
//
//        val fullList = itemsService.getItemsByPage(criteriaArgs)?.subList(pageSize*pageNumber+1, pageSize*pageNumber+pageSize)
//        val outputList = fullList?.subList(pageSize*pageNumber+1, pageSize*pageNumber+pageSize)
//
//        return RecordsRes(outputList as List<Map<String, Any>>?, fullList?.size)
//    }

    @GetMapping("/getRecordByPage")
    fun getAllItemsByPage(
        request: HttpServletRequest
    ): RecordsRes<Map<String, Any>> {
        val criteriaArgs = CriteriaArgsBuilder.withRequest(request)
            .addStringLike("name")
            .addStringLike("code")
            .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 = itemsService.getItemsByPage(criteriaArgs) ?: emptyList()

        val paginatedList = PagingUtils.getPaginatedList(fullList,pageSize, pageNum)

        return RecordsRes(paginatedList as List<Map<String, Any>>, fullList.size)
    }
    @GetMapping("/pickOrderItems")
    fun getPickOrderItemsByPage(request: HttpServletRequest): RecordsRes<Map<String, Any>> {
        try {
            println("=== Debug: getPickOrderItemsByPage ===")
            println("Request parameters: ${request.parameterMap}")
            
            val criteriaArgs = CriteriaArgsBuilder.withRequest(request)
                .addStringLike("itemCode")
                .addStringLike("itemName")
                .addString("status")
                .addString("targetDateFrom")
                .addString("targetDateTo")
                .build()
            
            println("Criteria args: $criteriaArgs")
            
            val pageSize = request.getParameter("pageSize")?.toIntOrNull() ?: 10
            val pageNum = request.getParameter("pageNum")?.toIntOrNull() ?: 1
            
            println("Page size: $pageSize, Page num: $pageNum")
            
            val fullList = itemsService.getPickOrderItemsByPage(criteriaArgs)
            println("Full list size: ${fullList.size}")
            
            val paginatedList = PagingUtils.getPaginatedList(fullList, pageSize, pageNum)
            println("Paginated list size: ${paginatedList.size}")
            
            return RecordsRes(paginatedList, fullList.size)
        } catch (e: Exception) {
            println("Error in getPickOrderItemsByPage: ${e.message}")
            e.printStackTrace()
            throw e
        }
    }

    @GetMapping("/itemOrder/ordered")
    fun getItemOrderOrderedItems(
        @RequestParam(required = false) search: String?,
        @RequestParam(required = false) type: String?
    ): List<Map<String, Any>> {
        return itemsService.getItemOrderOrderedItems(search, type)
    }

    @GetMapping("/itemOrder/unordered")
    fun getItemOrderUnorderedItems(
        @RequestParam(required = false) search: String?,
        @RequestParam(required = false) type: String?
    ): List<Map<String, Any>> {
        return itemsService.getItemOrderUnorderedItems(search, type)
    }

    @GetMapping("/itemOrder/unordered/search")
    fun searchItemOrderUnorderedItems(
        @RequestParam search: String,
        @RequestParam(required = false) type: String?,
        @RequestParam(required = false, defaultValue = "200") limit: Int,
    ): List<Map<String, Any>> {
        return itemsService.searchItemOrderUnorderedItems(search, type, limit)
    }

    @PostMapping("/itemOrder/save")
    fun saveItemOrder(@RequestBody request: Map<String, Any>): MessageResponse {
        val idsAny = request["orderedItemIds"]
        val ids = when (idsAny) {
            is List<*> -> idsAny.mapNotNull {
                when (it) {
                    is Number -> it.toLong()
                    is String -> it.toLongOrNull()
                    else -> null
                }
            }
            else -> emptyList()
        }
        return itemsService.saveItemOrder(ids)
    }
    @GetMapping("/details/{id}")
    fun getItems(@PathVariable id: Long): ItemWithQcResponse {
        return itemsService.getItem(id)
    }

    @PostMapping("/new")
    fun saveItem(@Valid @RequestBody newItem: NewItemRequest): MessageResponse {
        println("`````TESTING`````")
        return itemsService.saveItem(newItem)
    }

    @DeleteMapping("/{id}")
    fun deleteItem(@PathVariable id: Long): Items {
        return itemsService.markDeleted(id)
    }

    @GetMapping("/itemsWithDetails")
fun getItemsWithDetailsByPage(request: HttpServletRequest): RecordsRes<Map<String, Any>> {
    val criteriaArgs = CriteriaArgsBuilder.withRequest(request)
        .addStringLike("name")
        .addStringLike("code")
        .addStringLike("description")
        .addString("type")
        .build()

    val pageSize = request.getParameter("pageSize")?.toIntOrNull() ?: 10
    val pageNum = request.getParameter("pageNum")?.toIntOrNull() ?: 1

    val fullList = itemsService.getItemsWithDetailsByPage(criteriaArgs)
    val paginatedList = PagingUtils.getPaginatedList(fullList, pageSize, pageNum)

    return RecordsRes(paginatedList, fullList.size)
}

    @GetMapping("/marketUnitPrice/template")
    fun downloadMarketUnitPriceTemplate(): ResponseEntity<ByteArray> {
        val bytes = itemsService.generateMarketUnitPriceTemplate()
        val headers = HttpHeaders().apply {
            contentType = MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
            setContentDispositionFormData("attachment", "market_unit_price_template.xlsx")
        }
        return ResponseEntity.ok().headers(headers).body(bytes)
    }

    @PostMapping("/marketUnitPrice/import")
    fun importMarketUnitPrice(@RequestParam("file") file: MultipartFile): ResponseEntity<Map<String, Any>> {
        if (file.isEmpty) {
            return ResponseEntity.badRequest().body(mapOf("success" to false, "updated" to 0, "errors" to listOf("No file uploaded.")))
        }
        val workbook = try {
            XSSFWorkbook(file.inputStream)
        } catch (e: Exception) {
            logger.warn("Failed to parse Excel file", e)
            return ResponseEntity.badRequest().body(mapOf("success" to false, "updated" to 0, "errors" to listOf("Invalid Excel file.")))
        }
        workbook.use {
            val result = itemsService.importMarketUnitPriceExcel(it)
            return ResponseEntity.ok(result)
        }
    }
}