package com.lukouguoji.gjc.viewModel

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.lukouguoji.gjc.R
import com.lukouguoji.gjc.holder.AssembleInfoViewHolder
import com.lukouguoji.gjc.holder.AssemblePositionViewHolder
import com.lukouguoji.gjc.holder.AssembleWaybillViewHolder
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.*
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.db.perference.SharedPreferenceUtil
import com.lukouguoji.module_base.http.net.NetApply
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.ktx.launchCollect
import com.lukouguoji.module_base.ktx.launchLoadingCollect
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody
import com.lukouguoji.module_base.model.ScanModel
import dev.utils.app.info.KeyValue
import kotlinx.coroutines.launch

/**
 * 国际出港-开始组装ViewModel（静态数据）
 */
class IntExpAssembleStartViewModel : BaseViewModel() {

    companion object {
        /**
         * 缓存用户上次选择的组装人
         * 生命周期：本次App打开期间有效，退出登录后清空
         */
        var lastSelectedOperator: String? = null
    }

    // ========== 搜索条件 ==========
    val searchText = MutableLiveData("")
    val uldSearchText = MutableLiveData("")  // ULD搜索框

    // ========== 组装参数（从选中运单自动提取）==========
    val assembleFlightNo = MutableLiveData("")      // 航班号
    val assembleFlightDate = MutableLiveData("")    // 航班日期

    // ========== 防抖标记 ==========
    private var lastQueriedAssembledParams = ""  // 避免重复查询

    // ========== 左侧组装信息列表 ==========
    val assembleInfoList = MutableLiveData<MutableList<AssembleInfoBean>>()
    val assembleInfoLayoutId = R.layout.item_assemble_info
    val assembleInfoViewHolder = AssembleInfoViewHolder::class.java

    // ========== 左侧组装位置列表 ==========
    val assemblePositionList = MutableLiveData<MutableList<AssemblePositionBean>>()
    val assemblePositionLayoutId = R.layout.item_assemble_position
    val assemblePositionViewHolder = AssemblePositionViewHolder::class.java

    // ========== 选中的组装位置 ==========
    val selectedPosition = MutableLiveData<AssemblePositionBean?>()

    // ========== 右侧运单列表 ==========
    val waybillList = MutableLiveData<MutableList<AssembleWaybillBean>>()
    val waybillLayoutId = R.layout.item_assemble_waybill
    val waybillViewHolder = AssembleWaybillViewHolder::class.java

    // ========== ULD信息 ==========
    val uldInfo = MutableLiveData(UldInfoBean())

    // ========== 运单信息 ==========
    val waybillInfo = MutableLiveData(WaybillInfoBean())

    // ========== 组装人（独立的LiveData，用于监听变化并更新缓存）==========
    val operator = MutableLiveData<String>("")

    // ========== 组装人列表 ==========
    val assemblerList = MutableLiveData<List<KeyValue>>(emptyList())

    // ========== 标记位，避免重复查询 ==========
    private var lastQueriedUldNo = ""

    // ========== 修改模式待匹配的组装位置 ==========
    private var pendingLoadArea: String = ""

    /**
     * ULD编号锁定状态（页面内编辑模式）
     */
    val isUldNoLocked = MutableLiveData(false)

    /**
     * 卸货时选中的组装信息子运单数据
     * 用于：
     * 1. 卸货校验时对比组装件数/重量
     * 2. 卸货提交时构建 wbInfo
     */
    private var selectedAssembleWaybill: AssembleInfoBean? = null

    /**
     * 是否从列表页"修改"模式进入
     * 与 isUldNoLocked 的区别：
     * - isFromEditMode：整个页面生命周期内 ULD 编号锁定，但不影响装货/卸货按钮
     * - isUldNoLocked：页面内编辑模式，影响装货/卸货按钮
     */
    val isFromEditMode = MutableLiveData(false)

    /**
     * 装货按钮启用状态（非编辑模式时启用）
     */
    val isLoadEnabled = MutableLiveData(true)

    /**
     * 卸货按钮启用状态（编辑模式时启用）
     */
    val isUnloadEnabled = MutableLiveData(false)

    init {
        // 监听组装人变化，自动更新缓存和waybillInfo
        operator.observeForever { value ->
            if (!value.isNullOrEmpty()) {
                lastSelectedOperator = value
                // 同步到 waybillInfo
                waybillInfo.value?.operator = value
            }
        }

        // 监听ULD锁定状态，自动更新按钮启用状态
        isUldNoLocked.observeForever { isLocked ->
            if (isLocked == true) {
                // 编辑模式：只能卸货
                isLoadEnabled.value = false
                isUnloadEnabled.value = true
            } else {
                // 非编辑模式：只能装货
                isLoadEnabled.value = true
                isUnloadEnabled.value = false
            }
        }
    }


    /**
     * 加载组装位置列表
     */
    fun loadAssemblePosition() {
        launchLoadingCollect({ NetApply.api.getDictListByLocation("GJCLOAD") }) {
            onSuccess = { result ->
                val list = result.data?.mapIndexed { index, dictBean ->
                    AssemblePositionBean().apply {
                        positionCode = dictBean.code  // 保存位置编码/ID
                        positionName = dictBean.name
                        isSelected = (index == 0)  // 默认选中第一项
                    }
                }?.toMutableList() ?: mutableListOf()

                // 检查是否有待匹配的组装位置（修改模式）
                if (pendingLoadArea.isNotEmpty() && list.isNotEmpty()) {
                    // 取消所有选中状态
                    list.forEach { it.isSelected = false }
                    // 查找并选中匹配项
                    val matchedItem = list.find { it.positionName == pendingLoadArea }
                    if (matchedItem != null) {
                        matchedItem.isSelected = true
                        selectedPosition.value = matchedItem
                    } else {
                        // 未找到匹配项，选中第一项
                        list[0].isSelected = true
                        selectedPosition.value = list[0]
                    }
                    // 清空待匹配标记
                    pendingLoadArea = ""
                    // 触发组装信息列表查询
                    loadAssembledList()
                } else if (list.isNotEmpty()) {
                    // 非修改模式，选中第一项
                    selectedPosition.value = list[0]
                }

                assemblePositionList.value = list
            }
        }
    }

    /**
     * 组装位置点击（单选切换）
     */
    fun onPositionItemClick(position: Int) {
        val list = assemblePositionList.value ?: return

        // 取消所有选中状态
        list.forEach { it.isSelected = false }

        // 选中当前项
        if (position in list.indices) {
            list[position].isSelected = true
            selectedPosition.value = list[position]
        }

        // 刷新列表
        assemblePositionList.value = list

        // 触发组装信息列表查询
        loadAssembledList()
    }

    /**
     * 运单点击（单选切换）
     * 装货模式：从运单列表选择运单
     */
    fun onWaybillItemClick(position: Int) {
        val list = waybillList.value ?: return

        // 选中新运单前，先检查是否切换了运单
        val previousWaybillNo = waybillInfo.value?.waybillNo ?: ""
        val selectedWaybill = if (position in list.indices) list[position] else null
        val isWaybillChanged = selectedWaybill != null && previousWaybillNo.isNotEmpty()
                                && selectedWaybill.waybillNo != previousWaybillNo

        // 取消所有运单的选中状态
        list.forEach { it.isSelected.set(false) }

        // 选中当前运单
        if (selectedWaybill != null) {
            selectedWaybill.isSelected.set(true)

            // 【删除】不再从运单提取航班信息（航班信息改为从ULD查询接口获取）

            // 【新增】清空卸货选中的子运单（切换到装货模式）
            selectedAssembleWaybill = null

            // 保存当前的组装人（始终保留，从operator LiveData读取）
            val previousOperator = operator.value ?: ""

            // 判断是否需要保留组装件数和重量
            val previousAssembleCount: String
            val previousAssembleWeight: String

            if (isWaybillChanged) {
                // 运单切换了：清空组装件数和组装重量
                previousAssembleCount = ""
                previousAssembleWeight = ""

                // 解锁ULD编号
                isUldNoLocked.value = false
            } else {
                // 同一个运单：保留组装件数和组装重量
                previousAssembleCount = waybillInfo.value?.assembleCount ?: ""
                previousAssembleWeight = waybillInfo.value?.assembleWeight ?: ""
            }

            // 同步运单信息到表单
            waybillInfo.value = WaybillInfoBean().apply {
                waybillNo = selectedWaybill.waybillNo
                waybillPieces = selectedWaybill.pieces
                waybillWeight = selectedWaybill.weight
                assembleCount = previousAssembleCount
                assembleWeight = previousAssembleWeight
                operator = previousOperator  // 从operator LiveData获取的值
            }
        }

        // 刷新列表
        waybillList.value = list

        // 清除防抖标记，强制重新查询组装信息列表
        lastQueriedAssembledParams = ""

        // 触发组装信息列表查询
        loadAssembledList()
    }

    /**
     * 扫码运单
     */
    fun scanWaybill() {
        ScanModel.startScan(getTopActivity(), Constant.RequestCode.WAYBILL)
    }

    /**
     * 加载待组装运单列表
     */
    fun loadWaitingAssembleWaybills() {
        val wbNo = searchText.value?.trim() ?: ""

        // 发起网络请求（空参数时相当于刷新列表）
        launchLoadingCollect({ NetApply.api.queryWaitingAssemble(wbNo) }) {
            onSuccess = { result ->
                // 数据转换: GjcWarehouse -> AssembleWaybillBean
                val warehouseList = result.data ?: mutableListOf()
                val waybillBeanList = warehouseList.map { warehouse ->
                    AssembleWaybillBean().apply {
                        waybillNo = warehouse.wbNo
                        pieces = warehouse.pc.toString()
                        weight = String.format("%.1f", warehouse.weight)
                        flight = warehouse.flight
                        fno = warehouse.fno
                        fdate = warehouse.fdate
                        whId = warehouse.whId  // 添加运单ID
                        isMarked = false
                    }
                }.toMutableList()

                // 更新列表
                waybillList.value = waybillBeanList

                // 检查当前填充的运单是否在新列表中
                val currentWaybillNo = waybillInfo.value?.waybillNo ?: ""
                if (currentWaybillNo.isNotEmpty()) {
                    val existsInNewList = waybillBeanList.any { it.waybillNo == currentWaybillNo }
                    if (!existsInNewList) {
                        // 当前运单不在新列表中，清空表单
                        val previousOperator = operator.value ?: ""
                        waybillInfo.value = WaybillInfoBean().apply {
                            operator = previousOperator
                        }
                    }
                }

                // 结果反馈
                if (waybillBeanList.isEmpty()) {
                    showToast("未找到待组装运单")
                } else {
                    showToast("查询成功，共${waybillBeanList.size}条记录")
                }
            }
            onFailed = { code, message ->
                showToast("查询失败: $message")
                waybillList.value = mutableListOf()
            }
        }
    }

    /**
     * 初始化加载待组装运单列表（页面打开时调用）
     */
    fun loadInitialWaitingAssemble() {
        launchLoadingCollect({ NetApply.api.queryWaitingAssemble("") }) {
            onSuccess = { result ->
                val warehouseList = result.data ?: mutableListOf()
                val waybillBeanList = warehouseList.map { warehouse ->
                    AssembleWaybillBean().apply {
                        waybillNo = warehouse.wbNo
                        pieces = warehouse.pc.toString()
                        weight = String.format("%.1f", warehouse.weight)
                        flight = warehouse.flight
                        fno = warehouse.fno
                        fdate = warehouse.fdate
                        whId = warehouse.whId  // 添加运单ID
                        isMarked = false
                    }
                }.toMutableList()

                waybillList.value = waybillBeanList

                // 检查当前填充的运单是否在新列表中
                val currentWaybillNo = waybillInfo.value?.waybillNo ?: ""
                if (currentWaybillNo.isNotEmpty()) {
                    val existsInNewList = waybillBeanList.any { it.waybillNo == currentWaybillNo }
                    if (!existsInNewList) {
                        // 当前运单不在新列表中，清空表单
                        val previousOperator = operator.value ?: ""
                        waybillInfo.value = WaybillInfoBean().apply {
                            operator = previousOperator
                        }
                    }
                }

                if (waybillBeanList.isEmpty()) {
                    showToast("暂无待组装运单")
                }
            }
            onFailed = { code, message ->
                showToast("加载失败: $message")
                waybillList.value = mutableListOf()
            }
        }
    }

    /**
     * 加载组装人列表
     */
    fun loadAssemblerList() {
        launchCollect({ NetApply.api.getIntExpAssemblerList() }) {
            onSuccess = { result ->
                val list = result.data ?: emptyList()
                // 转换为 KeyValue 列表
                val keyValueList = list.map { KeyValue(it, it) }
                assemblerList.value = keyValueList

                // 使用缓存的组装人，如果缓存存在且在列表中则自动填充
                if (!lastSelectedOperator.isNullOrEmpty() && list.contains(lastSelectedOperator)) {
                    operator.value = lastSelectedOperator  // 设置到operator LiveData，会自动触发observer更新缓存和waybillInfo
                }
                // 如果缓存为空或不在列表中，保持为空（显示hint "请选择组装人"）
            }
            onFailed = { code, message ->
                showToast("加载组装人列表失败: $message")
                assemblerList.value = emptyList()
            }
        }
    }


    /**
     * ULD编号输入完成时调用
     */
    fun onUldNoInputComplete() {
        val uld = uldInfo.value?.uldNo?.trim() ?: ""
        if (uld.isNotEmpty() && uld != lastQueriedUldNo) {
            lastQueriedUldNo = uld
            queryUldInfo(uld)
        }
    }

    /**
     * 查询ULD信息（状态和耗材重量）
     * 同时从ULD信息提取航班信息，并触发组装信息列表查询
     */
    private fun queryUldInfo(uldNo: String) {
        launchCollect({ NetApply.api.getUldWithConsumeWeight(uldNo) }) {
            onSuccess = { result ->
                val uldBean = result.data
                if (uldBean != null) {
                    // 更新ULD状态和耗材重量
                    uldInfo.value = uldInfo.value?.apply {
                        // status: 0-正常, 1-故障
                        uldStatus = when (uldBean.status) {
                            "0" -> "正常"
                            "1" -> "故障"
                            else -> uldBean.status ?: ""
                        }
                        // 耗材重量保持可编辑，仅在为空时填充
                        if (materialWeight.isEmpty()) {
                            materialWeight = uldBean.consumeWeight?.toString() ?: ""
                        }
                        // 保存useId（用于装货/卸货接口）
                        useId = uldBean.useId
                    }

                    // 【新增】从ULD信息提取航班信息
                    if (uldBean.fno.isNotEmpty() && uldBean.fdate.isNotEmpty()) {
                        assembleFlightNo.value = uldBean.fno
                        assembleFlightDate.value = uldBean.fdateFormatted  // 使用格式化后的日期（只保留年月日）
                        // 清除防抖标记，触发组装信息列表查询
                        lastQueriedAssembledParams = ""
                        loadAssembledList()
                    } else {
                        // 航班信息为空，清空组装信息列表，但允许继续装货
                        assembleFlightNo.value = ""
                        assembleFlightDate.value = ""
                        assembleInfoList.value = mutableListOf()
                    }
                } else {
                    showToast("ULD 编号未维护，请先进行维护！")
                }
            }
            onFailed = { code, message ->
                showToast("查询ULD信息失败: $message")
            }
        }
    }

    /**
     * 重新查询 ULD 信息，仅回填最新的 useId 与 ULD 状态。
     *
     * 用途：以"新增"形式进入页面、对全新 ULD 首次装货时，服务端在首票成功后才生成
     * 该 ULD 的 use 记录（useId）。装货/卸货接口返回值（GjcWarehouse）不含 useId，
     * 若不回填，后续票仍以 useId=null 提交，会被服务端当作新的 use 处理，
     * 导致无法继续往同一 ULD 组装多票。此处在每次操作成功后回填最新 useId，
     * 保证多票组装提交到同一 ULD use 记录。
     *
     * 不在此处刷新航班/组装信息列表，避免与 loadAssembledList 的航班兜底逻辑相互覆盖。
     */
    private fun reloadUldUseId(uldNo: String) {
        if (uldNo.isEmpty()) return
        launchCollect({ NetApply.api.getUldWithConsumeWeight(uldNo) }) {
            onSuccess = { result ->
                val uldBean = result.data
                if (uldBean != null) {
                    // 仅回填 useId（用于后续装货/卸货提交到同一 ULD use 记录），
                    // 不改动 ULD 状态/耗材重量/航班等其它字段，避免影响表单现有逻辑。
                    uldInfo.value = uldInfo.value?.apply {
                        useId = uldBean.useId
                    }
                }
            }
        }
    }

    /**
     * 卸货按钮点击
     */
    fun onUnloadClick() {
        performAssembleOperation(isLoad = false)
    }

    /**
     * 装货按钮点击
     */
    fun onLoadClick() {
        performAssembleOperation(isLoad = true)
    }

    /**
     * 执行组装操作（卸货或装货）
     * @param isLoad true-装货，false-卸货
     *
     * 装货与卸货的区别：
     * 1. 校验逻辑不同：
     *    - 装货：与运单列表中的件数/重量对比
     *    - 卸货：与组装信息中的组装件数/重量对比
     * 2. wbInfo 来源不同：
     *    - 装货：从运单列表选中项获取
     *    - 卸货：从组装信息选中的子运单获取
     */
    private fun performAssembleOperation(isLoad: Boolean) {
        // 1. 验证必填字段
        val uldNo = uldInfo.value?.uldNo?.trim() ?: ""
        if (uldNo.isEmpty()) {
            showToast("请输入ULD编号")
            return
        }

        val materialWeight = uldInfo.value?.materialWeight?.trim() ?: ""
        if (materialWeight.isEmpty()) {
            showToast("请输入耗材重量")
            return
        }

        val waybillNo = waybillInfo.value?.waybillNo?.trim() ?: ""
        if (waybillNo.isEmpty()) {
            showToast("请选择运单")
            return
        }

        val assembleCount = waybillInfo.value?.assembleCount?.trim() ?: ""
        if (assembleCount.isEmpty()) {
            val countFieldName = if (isLoad) "装货件数" else "卸货件数"
            showToast("请输入${countFieldName}")
            return
        }

        val assembleWeight = waybillInfo.value?.assembleWeight?.trim() ?: ""

        // 【修改】区分校验逻辑
        val assembleCountInt = assembleCount.toLongOrNull() ?: 0L
        val assembleWeightDouble = assembleWeight.toDoubleOrNull() ?: 0.0

        if (isLoad) {
            // 装货校验：与运单列表中的件数/重量对比
            val waybillPieces = waybillInfo.value?.waybillPieces?.trim() ?: ""
            val waybillPiecesInt = waybillPieces.toLongOrNull() ?: 0L

            if (waybillPiecesInt > 0 && assembleCountInt > waybillPiecesInt) {
                showToast("装货件数不能大于运单件数")
                return
            }

            if (assembleWeight.isNotEmpty()) {
                val waybillWeight = waybillInfo.value?.waybillWeight?.trim() ?: ""
                val waybillWeightDouble = waybillWeight.toDoubleOrNull() ?: 0.0

                if (waybillWeightDouble > 0 && assembleWeightDouble > waybillWeightDouble) {
                    showToast("装货重量不能大于运单重量")
                    return
                }
            }
        } else {
            // 卸货校验：与组装信息中的组装件数/重量对比
            val assembleInfo = selectedAssembleWaybill?.waybillData
            if (assembleInfo == null) {
                showToast("请从组装信息列表选择要卸货的运单")
                return
            }

            // originalPieces 对应 checkInPc（已组装件数）
            val maxPieces = assembleInfo.originalPieces.toLongOrNull() ?: 0L
            // originalWeight 对应 checkInWeight（已组装重量）
            val maxWeight = assembleInfo.originalWeight.toDoubleOrNull() ?: 0.0

            if (maxPieces > 0 && assembleCountInt > maxPieces) {
                showToast("卸货件数不能大于已组装件数")
                return
            }

            if (assembleWeight.isNotEmpty() && maxWeight > 0 && assembleWeightDouble > maxWeight) {
                showToast("卸货重量不能大于已组装重量")
                return
            }
        }

        val operatorValue = operator.value?.trim() ?: ""
        if (operatorValue.isEmpty()) {
            showToast("请选择组装人")
            return
        }

        val loadArea = selectedPosition.value?.positionName?.trim() ?: ""
        if (loadArea.isEmpty()) {
            showToast("请选择组装位置")
            return
        }

        val loadAreaId = selectedPosition.value?.positionCode?.trim() ?: ""

        // 2. 构建useInfo（ULD信息）
        val useInfo = mapOf(
            "uld" to uldNo,
            "consumeWeight" to materialWeight.toDoubleOrNull(),
            "status" to when (uldInfo.value?.uldStatus) {
                "正常" -> "0"
                "故障" -> "1"
                else -> ""
            },
            "loadArea" to loadArea,
            "loadAreaId" to loadAreaId.ifEmpty { null },  // 组装位置ID
            "useId" to if (uldInfo.value?.useId == 0L) null else uldInfo.value?.useId  // 添加useId（来自getUld接口）
        )

        // 3. 【修改】区分 wbInfo 构建
        val wbInfo: Map<String, Any?>

        // 记录本次操作运单的航班信息（用于操作成功后刷新组装信息列表）
        var operationFno = ""
        var operationFdate = ""

        if (isLoad) {
            // 装货：从运单列表获取
            val currentWaybillList = waybillList.value
            if (currentWaybillList == null) {
                showToast("运单列表为空")
                return
            }

            val selectedWaybill = currentWaybillList.firstOrNull { it.isSelected.get() }
            if (selectedWaybill == null) {
                showToast("请选择运单")
                return
            }

            // 使用原始运单件数/重量（如果有），否则使用当前件数/重量
            val waybillPc = if (selectedWaybill.originalPieces.isNotEmpty()) {
                selectedWaybill.originalPieces.toLongOrNull()
            } else {
                selectedWaybill.pieces.toLongOrNull()
            }
            val waybillWeight = if (selectedWaybill.originalWeight.isNotEmpty()) {
                selectedWaybill.originalWeight.toDoubleOrNull()
            } else {
                selectedWaybill.weight.toDoubleOrNull()
            }

            operationFno = selectedWaybill.fno
            operationFdate = selectedWaybill.fdate

            wbInfo = mapOf(
                "wbNo" to selectedWaybill.waybillNo,
                "pc" to waybillPc,
                "weight" to waybillWeight,
                "fdate" to selectedWaybill.fdate,
                "fno" to selectedWaybill.fno,
                "whId" to selectedWaybill.whId
            )
        } else {
            // 卸货：从组装信息子运单获取
            val assembleWaybill = selectedAssembleWaybill?.waybillData
            if (assembleWaybill == null) {
                showToast("请从组装信息列表选择要卸货的运单")
                return
            }

            operationFno = assembleWaybill.fno
            operationFdate = assembleWaybill.fdate

            wbInfo = mapOf(
                "wbNo" to assembleWaybill.waybillNo,
                "pc" to assembleWaybill.pieces.toLongOrNull(),      // 运单件数
                "weight" to assembleWaybill.weight.toDoubleOrNull(), // 运单重量
                "fdate" to assembleWaybill.fdate,
                "fno" to assembleWaybill.fno,
                "whId" to assembleWaybill.whId
            )
        }

        // 4. 构建完整请求参数
        val params = mapOf(
            "abPc" to assembleCount.toLongOrNull(),
            "abWeight" to assembleWeight.toDoubleOrNull(),
            "consumeWeight" to materialWeight.toDoubleOrNull(),
            "ldId" to operatorValue,
            "loadArea" to loadArea,
            "loadAreaId" to loadAreaId.ifEmpty { null },  // 组装位置ID
            "useInfo" to useInfo,
            "wbInfo" to wbInfo,
            "userId" to SharedPreferenceUtil.getString(Constant.Share.account)
        ).toRequestBody()

        // 5. 调用接口（带Loading，等待接口返回）
        val operationName = if (isLoad) "装货" else "卸货"
        launchLoadingCollect({
            if (isLoad) {
                NetApply.api.assembleLoadCargo(params)
            } else {
                NetApply.api.assembleDropCargo(params)
            }
        }) {
            onSuccess = { result ->
                // 接口成功后才显示成功提示并刷新列表
                handleOperationSuccess(operationName, isLoad, uldNo, operationFno, operationFdate)
            }
            onFailed = { code, message ->
                showToast("${operationName}失败: $message")
            }
        }
    }

    /**
     * 处理装货/卸货操作成功
     */
    private fun handleOperationSuccess(
        operationName: String,
        isLoad: Boolean,
        uldNo: String,
        operationFno: String,
        operationFdate: String
    ) {
        showToast("${operationName}成功")

        // 发送刷新事件，通知出港组装列表页面更新数据
        viewModelScope.launch {
            FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).emit("refresh")
        }

        // 清空表单（在刷新数据前清空，避免刷新时的状态冲突）
        clearForm()

        // 回填最新 useId（关键，用于后续装货/卸货提交到同一 ULD use 记录）：
        // - 装货：以"新增"形式进入、对全新 ULD 首票装货时，服务端在首票成功后才生成
        //   该 ULD 的 use 记录，而接口返回值不含 useId，不回填则后续票以 useId=null 提交、
        //   被当作新 use 处理，无法继续多票。仅在本地 useId 尚未生成（为 0）时回填，
        //   "修改"模式及已过磅 ULD 本就带 useId，保持原逻辑不变。
        // - 卸货：从组装信息列表选票卸货，同一 ULD 因 lastQueriedUldNo 防抖不会重新查询 ULD，
        //   useId 会停留在卸首票前的陈旧值，故卸货成功后无条件重拉，保证可连续卸多票。
        if (isLoad) {
            if ((uldInfo.value?.useId ?: 0L) == 0L) {
                reloadUldUseId(uldNo)
            }
        } else {
            reloadUldUseId(uldNo)
        }

        // 同步航班信息，保证左侧组装信息列表查询的是本次操作 ULD 所属航班：
        // - 装货：装货决定该 ULD 归属哪个航班。若在同一 ULD 上先卸光原航班(如 MU0128)货物、
        //   再装入另一航班(如 MU0205)的货，必须无条件把航班改为本次所装运单的航班，
        //   否则 assembleFlightNo 仍停留在旧航班，左侧组装信息列表会继续显示旧航班的 ULD。
        // - 卸货：卸货不改变 ULD 归属航班，沿用原有"仅航班为空时兜底补全"逻辑。
        if (operationFno.isNotEmpty() && operationFdate.isNotEmpty()) {
            val shouldUpdateFlight =
                isLoad || assembleFlightNo.value.isNullOrEmpty() || assembleFlightDate.value.isNullOrEmpty()
            if (shouldUpdateFlight) {
                assembleFlightNo.value = operationFno
                // 与 ULD 查询保持一致，只取年月日（去掉时间部分）
                assembleFlightDate.value =
                    if (operationFdate.contains(" ")) operationFdate.split(" ")[0] else operationFdate
            }
        }

        // 清除防抖标记，强制刷新组装信息列表
        lastQueriedAssembledParams = ""
        loadAssembledList()

        // 刷新运单列表（使用当前搜索条件）
        refreshWaybillList()
    }

    /**
     * 刷新运单列表（保留当前搜索条件）
     */
    private fun refreshWaybillList() {
        val wbNo = searchText.value?.trim() ?: ""

        launchLoadingCollect({ NetApply.api.queryWaitingAssemble(wbNo) }) {
            onSuccess = { result ->
                val warehouseList = result.data ?: mutableListOf()
                val waybillBeanList = warehouseList.map { warehouse ->
                    AssembleWaybillBean().apply {
                        waybillNo = warehouse.wbNo
                        pieces = warehouse.pc.toString()
                        weight = String.format("%.1f", warehouse.weight)
                        flight = warehouse.flight
                        fno = warehouse.fno
                        fdate = warehouse.fdate
                        whId = warehouse.whId
                        isMarked = false
                    }
                }.toMutableList()

                waybillList.value = waybillBeanList
            }
            onFailed = { code, message ->
                showToast("刷新运单列表失败: $message")
            }
        }
    }

    /**
     * 组装信息列表点击事件
     * 1. 点击一级ULD行：展开/折叠（按需加载运单列表）
     * 2. 点击二级运单行：填充表单（编辑模式）
     */
    fun onAssembleInfoItemClick(position: Int) {
        val list = assembleInfoList.value ?: return
        if (position !in list.indices) return

        val clickedItem = list[position]

        when (clickedItem.itemType) {
            AssembleInfoBean.ItemType.ULD_HEADER -> {
                // 一级ULD行：切换展开/折叠
                val newExpandState = !clickedItem.isExpanded.get()
                clickedItem.isExpanded.set(newExpandState)

                if (newExpandState) {
                    // 展开：查询该ULD的运单列表
                    loadWaybillsByUld(position, clickedItem)
                } else {
                    // 折叠：移除二级运单行
                    removeWaybillRows(position)
                }
            }

            AssembleInfoBean.ItemType.WAYBILL_DETAIL -> {
                // 二级运单行：填充表单（编辑模式）
                fillFormFromWaybillDetail(clickedItem)
            }
        }
    }

    /**
     * 加载指定ULD的运单列表
     */
    private fun loadWaybillsByUld(uldPosition: Int, uldItem: AssembleInfoBean) {
        val uldBean = uldItem.tag as? GjcUldUseBean ?: return

        // 检查是否已缓存
        if (uldBean.waybillDetails != null) {
            // 已缓存，直接展开
            insertWaybillRows(uldPosition, uldBean.waybillDetails!!)
            return
        }

        // 未缓存，调用接口查询
        val params = uldBean.toRequestBody()

        launchLoadingCollect({ NetApply.api.getAssembledWaybillsByUld(params) }) {
            onSuccess = { result ->
                val waybillList = result.data ?: emptyList()

                if (waybillList.isEmpty()) {
                    showToast("该ULD暂无运单记录")
                    // 折叠回去
                    uldItem.isExpanded.set(false)
                } else {
                    // 缓存到GjcUldUseBean
                    uldBean.waybillDetails = waybillList.toMutableList()

                    // 插入二级运单行
                    insertWaybillRows(uldPosition, waybillList)
                }
            }
            onFailed = { code, message ->
                showToast("查询失败: $message")
                // 折叠回去
                uldItem.isExpanded.set(false)
            }
        }
    }

    /**
     * 在指定位置后插入二级运单行
     */
    private fun insertWaybillRows(uldPosition: Int, waybillList: List<GjcWarehouse>) {
        val list = assembleInfoList.value?.toMutableList() ?: return
        val uldItem = list[uldPosition]

        // 生成二级运单行
        val waybillRows = waybillList.map { warehouse ->
            AssembleInfoBean().apply {
                itemType = AssembleInfoBean.ItemType.WAYBILL_DETAIL
                parentUldNo = uldItem.uldNo
                wbNo = warehouse.wbNo
                waybillPieces = warehouse.checkInPc.toInt()
                waybillWeight = warehouse.checkInWeight
                showIndent = true
                showIndex = false

                // 转换为AssembleWaybillBean（用于填充表单）
                waybillData = AssembleWaybillBean().apply {
                    waybillNo = warehouse.wbNo
                    pieces = warehouse.pc.toString()
                    weight = String.format("%.1f", warehouse.weight)
                    flight = warehouse.flight
                    fno = warehouse.fno
                    fdate = warehouse.fdate
                    whId = warehouse.whId
                    // 设置原始运单件数/重量（使用checkInPc/checkInWeight）
                    originalPieces = warehouse.checkInPc.toString()
                    originalWeight = String.format("%.1f", warehouse.checkInWeight)
                }
            }
        }

        // 插入到ULD行后面
        list.addAll(uldPosition + 1, waybillRows)
        assembleInfoList.value = list
    }

    /**
     * 移除指定ULD后的二级运单行
     */
    private fun removeWaybillRows(uldPosition: Int) {
        val list = assembleInfoList.value?.toMutableList() ?: return
        val uldItem = list[uldPosition]

        // 移除该ULD的所有二级行
        list.removeAll {
            it.itemType == AssembleInfoBean.ItemType.WAYBILL_DETAIL &&
            it.parentUldNo == uldItem.uldNo
        }

        assembleInfoList.value = list
    }

    /**
     * 从二级运单行填充表单（卸货模式）
     * 1. 存储选中的组装信息子运单（用于卸货校验和提交）
     * 2. 填充ULD信息（并锁定ULD编号）
     * 3. 填充运单信息（字段对调：运单件数/组装件数对调，运单重量/组装重量对调）
     *
     * 卸货时字段映射：
     * - 运单件数 ← pieces (pc，原始运单件数)
     * - 运单重量 ← weight (weight，原始运单重量)
     * - 组装件数 ← originalPieces (checkInPc，已组装件数，可编辑卸货数量)
     * - 组装重量 ← originalWeight (checkInWeight，已组装重量，可编辑卸货数量)
     */
    private fun fillFormFromWaybillDetail(item: AssembleInfoBean) {
        val waybill = item.waybillData ?: return

        // 【新增】存储选中的组装信息子运单（用于卸货校验和提交）
        selectedAssembleWaybill = item

        // 1. 填充ULD信息
        uldInfo.value = uldInfo.value?.apply {
            uldNo = item.parentUldNo
            // 耗材重量、ULD状态保持不变
        }

        // 保存当前的组装人（在创建新对象前，从operator LiveData读取）
        val previousOperator = operator.value ?: ""

        // 2. 填充运单信息（【修改】对调字段填充）
        waybillInfo.value = WaybillInfoBean().apply {
            waybillNo = waybill.waybillNo
            waybillPieces = waybill.pieces           // 【对调】显示运单件数（pc）
            waybillWeight = waybill.weight           // 【对调】显示运单重量（weight）
            assembleCount = waybill.originalPieces   // 【对调】显示组装件数（checkInPc），可编辑卸货数量
            assembleWeight = waybill.originalWeight  // 【对调】显示组装重量（checkInWeight），可编辑卸货数量
            operator = previousOperator  // 保留之前选择的组装人
        }

        // 3. 锁定ULD编号
        isUldNoLocked.value = true

        // 4. 查询ULD信息（如果需要）
        if (item.parentUldNo != lastQueriedUldNo) {
            lastQueriedUldNo = item.parentUldNo
            queryUldInfo(item.parentUldNo)
        }
    }

    /**
     * 查询已组装的ULD列表
     * 参数来源：
     * - fno/fdate：从当前选中的运单自动提取
     * - loadArea：从当前选中的组装位置获取
     * - uld：从ULD搜索框获取（可选）
     */
    fun loadAssembledList() {
        // 1. 参数验证
        val fno = assembleFlightNo.value ?: ""
        val fdate = assembleFlightDate.value ?: ""
        val loadArea = selectedPosition.value?.positionName ?: ""
        val uldSearch = uldSearchText.value ?: ""

        // 必填参数检查
        if (fno.isEmpty() || fdate.isEmpty() || loadArea.isEmpty()) {
            // 参数缺失，清空列表（静默处理）
            assembleInfoList.value = mutableListOf()
            return
        }

        // 2. 防抖检查（避免重复查询）
        val currentParams = "$fno|$fdate|$loadArea|$uldSearch"
        if (currentParams == lastQueriedAssembledParams) {
            return
        }
        lastQueriedAssembledParams = currentParams

        // 3. 构建请求参数
        val params = mapOf(
            "fno" to fno,
            "fdate" to fdate,
            "loadArea" to loadArea,
            "uld" to uldSearch.ifEmpty { null }  // 空值时传null
        ).toRequestBody()

        // 4. 调用接口
        launchLoadingCollect({ NetApply.api.getAssembledList(params) }) {
            onSuccess = { result ->
                val uldList = result.data ?: emptyList()

                if (uldList.isEmpty()) {
                    showToast("暂无已组装记录")
                    assembleInfoList.value = mutableListOf()
                } else {
                    // 转换为AssembleInfoBean列表
                    convertToAssembleInfoBeans(uldList)
                }
            }
            onFailed = { code, message ->
                showToast("查询失败: $message")
                assembleInfoList.value = mutableListOf()
            }
        }
    }

    /**
     * 数据转换: List<GjcAssembled> → List<AssembleInfoBean>
     * 只生成一级ULD行，不包含二级运单行
     * 同时将运单列表缓存到uldBean.waybillDetails
     */
    private fun convertToAssembleInfoBeans(assembledList: List<GjcAssembled>) {
        val infoList = assembledList.mapIndexed { index, assembled ->
            val uldBean = assembled.uldUse
            val warehouseList = assembled.warehouseList

            if (uldBean == null) {
                return@mapIndexed null
            }

            // 缓存运单列表到uldBean（展开时不需要再次查询）
            if (warehouseList != null && warehouseList.isNotEmpty()) {
                uldBean.waybillDetails = warehouseList
            }

            // 计算总件数和总重量（从子列表的checkInPc、checkInWeight求和）
            val calculatedPieces = warehouseList?.sumOf { it.checkInPc.toInt() } ?: 0
            val calculatedWeight = warehouseList?.sumOf { it.checkInWeight } ?: 0.0

            AssembleInfoBean().apply {
                itemType = AssembleInfoBean.ItemType.ULD_HEADER
                uldNo = uldBean.uld
                uldIndex = index + 1

                // 使用计算的总件数和总重量
                totalPieces = calculatedPieces
                totalWeight = calculatedWeight

                hasArrow = true
                showIndex = true
                isExpanded.set(false)  // 默认折叠

                // 关联原始ULD数据（用于点击展开时查询）
                tag = uldBean  // 使用tag存储GjcUldUseBean对象
            }
        }.filterNotNull().toMutableList()

        assembleInfoList.value = infoList
    }

    /**
     * ULD搜索框输入完成回调
     */
    fun onUldSearchInputComplete() {
        loadAssembledList()
    }

    /**
     * 清空表单并退出编辑模式
     */
    private fun clearForm() {
        // 保留组装人的值（用户期望保留上一次的选择，从operator LiveData读取）
        val previousOperator = operator.value ?: ""

        waybillInfo.value = WaybillInfoBean().apply {
            operator = previousOperator  // 恢复组装人
        }
        isUldNoLocked.value = false

        // 【新增】清空卸货选中的子运单
        selectedAssembleWaybill = null
    }

    /**
     * 清空缓存的组装人（登出时调用）
     */
    fun clearCachedOperator() {
        lastSelectedOperator = null
    }

    /**
     * 从列表页"修改"模式初始化
     * @param uldNo ULD编号
     * @param loadArea 组装位置（用于自动选中对应的组装位置）
     */
    fun initFromEditMode(uldNo: String, loadArea: String = "") {
        if (uldNo.isEmpty()) return

        // 标记为修改模式（整个页面生命周期内 ULD 编号锁定）
        isFromEditMode.value = true

        // 保存待匹配的组装位置（在组装位置列表加载完成后进行匹配选择）
        if (loadArea.isNotEmpty()) {
            pendingLoadArea = loadArea
        }

        // 填充 ULD 编号
        uldInfo.value = uldInfo.value?.apply {
            this.uldNo = uldNo
        } ?: UldInfoBean().apply {
            this.uldNo = uldNo
        }

        // 将 ULD 编号填充到左上角 ULD 列表筛选框，使组装信息列表只查询该 ULD。
        // loadAssembledList() 会读取 uldSearchText 作为 uld 查询参数，因此只显示这一个 ULD 的组装信息。
        // 用户可手动清空该筛选框后重新查询，即可查看该航班的全部组装信息。
        uldSearchText.value = uldNo

        // 更新防抖标记，确保查询能触发
        lastQueriedUldNo = ""

        // 触发 ULD 编码查询
        onUldNoInputComplete()
    }
}
