package com.ffii.fpsms.m18.model

import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonProperty

/**
 * M18 save payload for Shop BOM (udfBomForShop).
 * PUT /root/api/save/udfbomforshop?menuCode=udfbomforshop
 *
 * Same idea as GRN (`mainan` + `ant`): header and lines each wrapped as `{ "values": [ ... ] }`.
 * Root keys: **`udfbomforshop`** and **`udfproduct`** (same as M18 read [M18BomData]).
 * (Spelling is **udf**, not "uni".)
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
data class M18BomForShopSaveRequest(
    @JsonProperty("udfbomforshop")
    val udfbomforshop: M18MainUdfBomForShopWrapper,
    @JsonProperty("udfproduct")
    val udfproduct: M18UdfProductWrapper,
)

@JsonInclude(JsonInclude.Include.NON_NULL)
data class M18MainUdfBomForShopWrapper(
    val values: List<M18MainUdfBomForShopValue>,
)

/**
 * Header row for udfBomForShop. Field names match M18 read/sample JSON.
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
data class M18MainUdfBomForShopValue(
    /**
     * Existing M18 udfBomForShop header id for **update** (same as FPSMS [Bom.m18Id] after first sync).
     * Omit or null for **create**. Sent as JSON string for M18 compatibility (like GRN mainan `id`).
     */
    val id: String? = null,
    val code: String? = null,
    val beId: Int? = null,
    val desc: String? = null,
    @JsonProperty("desc_en")
    val descEn: String? = null,
    @JsonProperty("udfBOMCode")
    val udfBomCode: String? = null,
    val rev: String? = null,
    val udfUnit: Long? = null,
    /** Harvest qty: [Bom.outputQty] × pack multiple from header item stock UOM code (e.g. PACK2LB → ×2), else plain output qty. */
    val udfHarvest: String? = null,
    /** Trailing unit letters from that code (e.g. LB); null if code not parsed. */
    val udfHarvestUnit: String? = null,
    /** Epoch milliseconds (M18-style; same as read `lastModifyDate`). From FPSMS [com.ffii.core.entity.BaseEntity.created] in Asia/Hong_Kong. */
    @JsonProperty("udfeffectivedate")
    val udfEffectiveDate: Long? = null,
    @JsonProperty("udfYieldratePP")
    val udfYieldratePP: Number? = null,
    val udftypeoffood: String? = null,
    @JsonProperty("udfconfirmed")
    val udfconfirmed: Boolean? = null,
    val staffId: Int? = null,
    val flowTypeId: Int? = null,
    val virDeptId: Int? = null,
    val status: String? = null,
)

@JsonInclude(JsonInclude.Include.NON_NULL)
data class M18UdfProductWrapper(
    val values: List<M18UdfProductSaveValue>,
)

/**
 * Line payload for `udfproduct.values[]`. **`udfBaseUnit`** is the FPSMS UOM **code** for the line.
 * **`udfPackingUnit`** / **`udfPackingQty`** / **`udfproremark`** are not sent.
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
data class M18UdfProductSaveValue(
    /** Line id in M18 when updating */
    val id: Long? = null,
    val udfqty: Number? = null,
    val udfProduct: Long? = null,
    val udfIngredients: String? = null,
    /** Line UOM: [com.ffii.fpsms.modules.master.entity.UomConversion.code] (same unit as [udfqty]). */
    val udfBaseUnit: String? = null,
    /** PO supplier [com.ffii.fpsms.modules.master.entity.Shop.m18Id] (via `purchase_order.supplierId`) for latest PO line matching material [com.ffii.fpsms.modules.master.entity.Items.code]. */
    val udfSupplier: Long? = null,
    /**
     * M18 UOM id for price/purchase unit on the **M18-linked** PO line (`m18DataLog` present):
     * [com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine.uomM18] (M18 `unitId`) then
     * [com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine.uom] → [com.ffii.fpsms.modules.master.entity.UomConversion.m18Id].
     */
    @JsonProperty("udfpurchaseUnit")
    val udfpurchaseUnit: Long? = null,
    /** Line sequence, e.g. "     1" */
    val itemNo: String? = null,
    val udfoptions: String? = null,
    val udfoption: Number? = null,
    val udfYieldRate: Number? = null,
)
