package com.ffii.fpsms.modules.deliveryOrder.web

import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrder
import com.ffii.fpsms.modules.deliveryOrder.entity.models.DeliveryOrderInfo
import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus
import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderService
import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderRequest
import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderResponse
import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderStatusRequest
import org.springframework.web.bind.annotation.GetMapping
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 com.ffii.fpsms.modules.deliveryOrder.web.models.DoDetailResponse
import com.ffii.fpsms.modules.deliveryOrder.web.models.ExportDNLabelsRequest
import com.ffii.fpsms.modules.deliveryOrder.web.models.ExportDeliveryNoteRequest
import com.ffii.fpsms.modules.deliveryOrder.web.models.PrintDNLabelsRequest
import com.ffii.fpsms.modules.deliveryOrder.web.models.PrintDeliveryNoteRequest
import com.ffii.fpsms.modules.deliveryOrder.web.models.ReleaseDoRequest
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import jakarta.servlet.http.HttpServletResponse
import jakarta.validation.Valid
import net.sf.jasperreports.engine.JasperExportManager
import net.sf.jasperreports.engine.JasperPrint
import org.hibernate.result.Output
import org.springframework.context.NoSuchMessageException
import org.springframework.web.bind.annotation.ModelAttribute
import java.io.OutputStream
import java.io.UnsupportedEncodingException
import java.text.ParseException
import java.time.LocalDateTime

@RequestMapping("/do")
@RestController
class DeliveryOrderController(
    private val deliveryOrderService: DeliveryOrderService,
) {
    @GetMapping("/list")
    fun getDoList(): List<DeliveryOrderInfo> {
        return deliveryOrderService.getDoList();
    }

    @GetMapping("/detail/{id}")
    fun getDetailedDo(@PathVariable id: Long): DoDetailResponse? {
        return deliveryOrderService.getDetailedDo(id);
    }

    @GetMapping("/search-code/{code}")
    fun searchByCode(@PathVariable code: String): List<DeliveryOrderInfo> {
        return deliveryOrderService.searchByCode(code);
    }

    @GetMapping("/search-shopname/{shopName}")
    fun searchByShopName(@PathVariable shopName: String): List<DeliveryOrderInfo> {
        return deliveryOrderService.searchByShopName(shopName);
    }

    @GetMapping("/search-status/{status}")
    fun searchByStatus(@PathVariable status: DeliveryOrderStatus): List<DeliveryOrderInfo> {
        return deliveryOrderService.searchByStatus(status);
    }

    @GetMapping("/search-orderdate/{start}&{end}")
    fun searchBetweenOrderDate(
        @PathVariable start: LocalDateTime?,
        @PathVariable end: LocalDateTime?
    ): List<DeliveryOrderInfo> {
        return deliveryOrderService.searchBetweenOrderDate(start, end);
    }

    @GetMapping("/search-DO/{code}&{shopName}&{status}&{orderStartDate}&{orderEndDate}&{estArrStartDate}&{estArrEndDate}")
    fun searchDO(
        @PathVariable code: String?,
        @PathVariable shopName: String?,
        @PathVariable status: DeliveryOrderStatus?,
        @PathVariable orderStartDate: LocalDateTime?,
        @PathVariable orderEndDate: LocalDateTime?,
        @PathVariable estArrStartDate: LocalDateTime?,
        @PathVariable estArrEndDate: LocalDateTime?
    ): List<DeliveryOrderInfo> {
        println("test");
        if (code != null || shopName != null) {
            if (orderStartDate != null && orderEndDate != null && estArrStartDate != null && estArrEndDate != null) {
                if (status != null) {
                    return deliveryOrderService.searchAll(
                        code,
                        shopName,
                        status,
                        orderStartDate,
                        orderEndDate,
                        estArrStartDate,
                        estArrEndDate
                    );
                } else {
                    return deliveryOrderService.searchWithoutStatus(
                        code,
                        shopName,
                        orderStartDate,
                        orderEndDate,
                        estArrStartDate,
                        estArrEndDate
                    );
                }
            } else {
                if (orderStartDate == null && orderEndDate == null && estArrStartDate == null && estArrEndDate == null) {
                    if (status != null) {
                        return deliveryOrderService.searchWithoutDate(code, shopName, status);
                    } else {
                        return deliveryOrderService.searchCodeAndShopName(code, shopName);
                    }
                } else {
                    if (estArrStartDate != null && estArrEndDate != null && (orderStartDate == null && orderEndDate == null)) {
                        if (status != null) {
                            return deliveryOrderService.searchWithoutOrderDate(
                                code,
                                shopName,
                                status,
                                estArrStartDate,
                                estArrEndDate
                            );
                        } else {
                            return deliveryOrderService.searchWithoutOrderDateAndStatus(
                                code,
                                shopName,
                                estArrStartDate,
                                estArrEndDate
                            );
                        }
                    } else if (orderStartDate != null && orderEndDate != null && (estArrStartDate == null && estArrEndDate == null)) {
                        if (status != null) {
                            return deliveryOrderService.searchAll(
                                code,
                                shopName,
                                status,
                                orderStartDate,
                                orderEndDate,
                                estArrStartDate,
                                estArrEndDate
                            );
                        } else {
                            return deliveryOrderService.searchWithoutStatus(
                                code,
                                shopName,
                                orderStartDate,
                                orderEndDate,
                                estArrStartDate,
                                estArrEndDate
                            );
                        }
                    } else {
                        return emptyList();
                    }
                }

            }
        }
        return deliveryOrderService.getFullList();


    }


    @PostMapping("/update-status")
    fun updateDoStatus(@RequestBody request: SaveDeliveryOrderStatusRequest): SaveDeliveryOrderResponse {
        return deliveryOrderService.updateDeliveryOrderStatus(request);
    }

    @PostMapping("/start")
    fun startDo(@RequestBody id: Long): SaveDeliveryOrderResponse {
        val request = SaveDeliveryOrderStatusRequest(
            id = id,
            status = DeliveryOrderStatus.RECEIVING.value
        )
        return deliveryOrderService.updateDeliveryOrderStatus(request);
    }

    @PostMapping("/release")
    fun releaseDeliveryOrder(@RequestBody request: ReleaseDoRequest): MessageResponse {
        // ✅ Simply pass the request directly - userId comes from frontend session
        return deliveryOrderService.releaseDeliveryOrder(request)
    }

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

    @GetMapping("print-DN")
    fun printDN(@RequestBody request: PrintDeliveryNoteRequest) {
        deliveryOrderService.printDeliveryNote(request)
    }

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

    @GetMapping("print-DNLabels")
    fun printDN(@RequestBody request: PrintDNLabelsRequest) {
        deliveryOrderService.printDNLabels(request)
    }
}