package com.ffii.fpsms.modules.report.service

import com.ffii.core.support.JdbcDao
import org.springframework.stereotype.Service

@Service
open class ItemQcFailReportService(
    private val jdbcDao: JdbcDao,
) {
    fun searchItemQcFailReport(
        stockCategory: String?,   // items.type (可逗号分隔)
        itemCode: String?,        // items.code (可逗号分隔, LIKE)
        lastInDateStart: String?, // stock_in_line.receiptDate >=
        lastInDateEnd: String?,   // stock_in_line.receiptDate <
    ): List<Map<String, Any>> {
        val args = mutableMapOf<String, Any>()

        val stockCategorySql = buildMultiValueExactClause(stockCategory, "it.type", "stockCategory", args)
        val itemCodeSql = buildMultiValueLikeClause(itemCode, "it.code", "itemCode", args)

        val lastInDateStartSql = if (!lastInDateStart.isNullOrBlank()) {
            val formattedDate = lastInDateStart.replace("/", "-")
            args["lastInDateStart"] = formattedDate
            "AND DATE(sil.receiptDate) >= DATE(:lastInDateStart)"
        } else ""

        val lastInDateEndSql = if (!lastInDateEnd.isNullOrBlank()) {
            val formattedDate = lastInDateEnd.replace("/", "-")
            args["lastInDateEnd"] = formattedDate
            "AND DATE(sil.receiptDate) <= DATE(:lastInDateEnd)"
        } else ""

        val sql = """
            SELECT
                COALESCE(it.type, '') AS stockSubCategory,
                COALESCE(it.code, '') AS itemNo,
                it.name AS itemName,
                COALESCE(uc.udfudesc, uc.code, '') AS unitOfMeasure,
                COALESCE(sil.lotNo, il.lotNo, '') AS lotNo,
                COALESCE(DATE_FORMAT(COALESCE(sil.expiryDate, il.expiryDate), '%Y-%m-%d'), '') AS expiryDate,

                /* 用 stock_in_line.jobOrderId 来判 IQC/EPQC */
                CASE WHEN sil.jobOrderId IS NOT NULL THEN 'EPQC' ELSE 'IQC' END AS qcType,

                /* QC Template Used：取 qc_category.code (例如 A1/B4/X1) */
                COALESCE(
                    qc.name,
                    (SELECT name
                    FROM qc_category
                    WHERE isDefault = 1
                    AND deleted = 0
                    LIMIT 1),
                    qc.name,
                    ''
                ) AS qcTemplate,

                /* QC Criteria with Defect：优先用 qc_item_category.description，否则用 qc_item */
                COALESCE(qic.description, qi.description, qi.name, '') AS qcDefectCriteria,

                /* Lot Qty / Defect Qty：按 jrxml 字段类型输出 String */
                TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM FORMAT(                COALESCE(
                  CASE WHEN sil.purchaseOrderLineId IS NOT NULL
                       THEN sil.acceptedQty
                       WHEN iu_purchase.id IS NOT NULL AND iu.id IS NOT NULL
                       THEN sil.acceptedQty * (iu_purchase.ratioN / NULLIF(iu_purchase.ratioD, 0)) / (iu.ratioN / NULLIF(iu.ratioD, 0))
                       ELSE sil.acceptedQty END, 0), 2))) AS lotQty,
                TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM FORMAT(COALESCE(qr.failQty, 0), 2))) AS defectQty,

                /* Ref Data (e.g temp)：目前库表只有 qc_result.remarks，可先放这里 */
                COALESCE(qr.remarks, '') AS refData,

                /* Remarks：若你之后有独立字段再补 */
                '' AS remark,

                /* Order Ref No：IQC 用 purchase_order.code；EPQC 用 job_order.code */
                CASE
                    WHEN sil.jobOrderId IS NOT NULL THEN COALESCE(jo.code, '')
                    ELSE COALESCE(po.code, '')
                END AS orderRefNo

            FROM qc_result qr
            INNER JOIN stock_in_line sil
                ON qr.stockInLineId = sil.id
               AND sil.deleted = 0
            INNER JOIN items it
                ON qr.itemId = it.id
               AND it.deleted = 0
            LEFT JOIN item_uom iu
                ON it.id = iu.itemId
               AND iu.stockUnit = 1
               AND iu.deleted = 0
            LEFT JOIN uom_conversion uc
                ON iu.uomId = uc.id
            LEFT JOIN item_uom iu_purchase
                ON it.id = iu_purchase.itemId
               AND iu_purchase.purchaseUnit = 1
               AND iu_purchase.deleted = 0
            LEFT JOIN inventory_lot il
                ON sil.inventoryLotId = il.id
               AND il.deleted = 0
            LEFT JOIN purchase_order po
                ON sil.purchaseOrderId = po.id
               AND po.deleted = 0
            LEFT JOIN job_order jo
                ON sil.jobOrderId = jo.id
               AND jo.deleted = 0

           LEFT JOIN items_qc_category_mapping iqcm
                ON iqcm.itemId = it.id
            AND iqcm.type = (CASE WHEN sil.jobOrderId IS NOT NULL THEN 'EPQC' ELSE 'IQC' END)
            LEFT JOIN qc_category qc
                ON qc.id = iqcm.qcCategoryId
            AND qc.deleted = 0

            LEFT JOIN qc_item qi
                ON qi.id = qr.qcItemId
            AND qi.deleted = 0
            LEFT JOIN qc_item_category qic
                ON qic.qcItemId = qi.id
            AND qic.qcCategoryId = COALESCE(
                    iqcm.qcCategoryId,
                    (SELECT id
                    FROM qc_category
                    WHERE isDefault = 1
                    AND deleted = 0
                    LIMIT 1)
                )

            WHERE
                qr.deleted = 0
                AND qr.qcPassed = 0
                $stockCategorySql
                $itemCodeSql
                $lastInDateStartSql
                $lastInDateEndSql

            ORDER BY
                it.type,
                it.code,
                COALESCE(sil.lotNo, il.lotNo, ''),
                CASE WHEN sil.jobOrderId IS NOT NULL THEN 'EPQC' ELSE 'IQC' END,
                COALESCE(qic.`order`, 9999),
                COALESCE(qi.code, '')
        """.trimIndent()
        val result = jdbcDao.queryForList(sql, args)

        return result
    }

    private fun buildMultiValueLikeClause(
        paramValue: String?,
        columnName: String,
        paramPrefix: String,
        args: MutableMap<String, Any>
    ): String {
        if (paramValue.isNullOrBlank()) return ""
        val values = paramValue.split(",").map { it.trim() }.filter { it.isNotBlank() }
        if (values.isEmpty()) return ""

        val conditions = values.mapIndexed { index, value ->
            val paramName = "${paramPrefix}_$index"
            args[paramName] = "%$value%"
            "$columnName LIKE :$paramName"
        }
        return "AND (${conditions.joinToString(" OR ")})"
    }

    private fun buildMultiValueExactClause(
        paramValue: String?,
        columnName: String,
        paramPrefix: String,
        args: MutableMap<String, Any>
    ): String {
        if (paramValue.isNullOrBlank()) return ""
        val values = paramValue.split(",").map { it.trim() }.filter { it.isNotBlank() }
        if (values.isEmpty()) return ""

        val conditions = values.mapIndexed { index, value ->
            val paramName = "${paramPrefix}_$index"
            args[paramName] = value
            "$columnName = :$paramName"
        }
        return "AND (${conditions.joinToString(" OR ")})"
    }
}