package com.lukouguoji.gjj.viewModel

import android.content.Intent
import android.view.View
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.common.Constant
import com.lukouguoji.module_base.common.ConstantEvent
import com.lukouguoji.module_base.common.DetailsPageType
import com.lukouguoji.module_base.http.net.NetApply
import com.lukouguoji.module_base.impl.FlowBus
import com.lukouguoji.module_base.ktx.finish
import com.lukouguoji.module_base.ktx.formatDate
import com.lukouguoji.module_base.ktx.launchCollect
import com.lukouguoji.module_base.ktx.launchLoadingCollect
import com.lukouguoji.module_base.ktx.noNull
import com.lukouguoji.module_base.ktx.showToast
import com.lukouguoji.module_base.ktx.toRequestBody
import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
import com.lukouguoji.module_base.util.DictUtils
import dev.utils.app.info.KeyValue
import dev.utils.common.DateUtils
import kotlinx.coroutines.launch

class GjjManifestAddViewModel : BaseViewModel() {

    // 页面类型（必须用LiveData）
    val pageType = MutableLiveData(DetailsPageType.Add)

    // 舱单ID（编辑时使用）
    var mfId: Long = 0

    // 编号和前缀（编辑时使用）
    var no: String = ""
    var prefix: String = ""

    // 航班ID
    var fid: String = ""

    // 航班日期（新增模式默认今天）
    val flightDate = MutableLiveData(DateUtils.getCurrentTime().formatDate())

    // 航班号
    val flightNo = MutableLiveData("")

    // 运单号
    val waybillNo = MutableLiveData("")

    // ========== 航班级联查询 ==========
    private var lastQueriedFlight = ""

    fun onFlightDateInputComplete() {
        lastQueriedFlight = ""
        queryFlightIfReady()
    }

    fun onFlightNoInputComplete() {
        queryFlightIfReady()
    }

    private fun queryFlightIfReady() {
        val fdate = flightDate.value
        val fno = flightNo.value
        if (fdate.isNullOrEmpty() || fno.isNullOrEmpty()) return

        val key = "$fdate-$fno"
        if (key == lastQueriedFlight) return
        lastQueriedFlight = key

        launchCollect({
            NetApply.api.getGjFlightBean(
                mapOf(
                    "fdate" to fdate,
                    "fno" to fno,
                    "ieFlag" to "I",
                ).toRequestBody()
            )
        }) {
            onSuccess = {
                if (it.verifySuccess() && it.data != null) {
                    val flight = it.data!!
                    fid = flight.fid.noNull()
                    departure.value = flight.fdep.noNull()
                    destination.value = flight.fdest.noNull()
                } else {
                    fid = ""
                    departure.value = ""
                    destination.value = ""
                    showToast(it.msg.noNull("获取航班信息失败"))
                }
            }
            onFailed = { _, _ ->
                fid = ""
                departure.value = ""
                destination.value = ""
            }
        }
    }

    // UN编号
    val unNumber = MutableLiveData("")

    // 运单件数
    val waybillNum = MutableLiveData("")

    // 运单重量
    val waybillWeight = MutableLiveData("")

    // 实到数量
    val actualNum = MutableLiveData("")

    // 实到重量
    val actualWeight = MutableLiveData("")

    // 计费重量
    val billingWeight = MutableLiveData("")

    // 始发港
    val departure = MutableLiveData("")

    // 目的港
    val destination = MutableLiveData("")

    // 航程（自动拼接：始发站-目的站）
    val range = MediatorLiveData<String>().apply {
        val update = {
            val dep = departure.value ?: ""
            val dest = destination.value ?: ""
            value = if (dep.isNotEmpty() || dest.isNotEmpty()) "$dep-$dest" else ""
        }
        addSource(departure) { update() }
        addSource(destination) { update() }
    }

    // 品名(中)
    val goodsNameCn = MutableLiveData("")

    // 品名(英)
    val goodsNameEn = MutableLiveData("")

    // 备注
    val remark = MutableLiveData("")


    // 业务类型 列表
    val businessTypeList = MutableLiveData<List<KeyValue>>()
    val businessType = MutableLiveData("")

    // 包装类型 列表
    val packageTypeList = MutableLiveData<List<KeyValue>>()
    val packageType = MutableLiveData("")

    // 代理列表
    val agentList = MutableLiveData<List<KeyValue>>()
    val agent = MutableLiveData("")

    // 特码列表
    val specialCodeList = MutableLiveData<List<KeyValue>>()
    val specialCode = MutableLiveData("")

    // 货物类型（无下拉列表，仅用于编辑模式回传）
    val goodsType = MutableLiveData("")

    // 运单类型
    val waybillTypeList = MutableLiveData<List<KeyValue>>()
    val waybillType = MutableLiveData("")

    /**
     * 初始化（从Intent获取参数）
     */
    fun initOnCreated(intent: Intent) {
        // 获取页面类型
        pageType.value = DetailsPageType.valueOf(
            intent.getStringExtra(Constant.Key.PAGE_TYPE) ?: DetailsPageType.Add.name
        )

        // 获取航班ID
        fid = intent.getStringExtra(Constant.Key.ID).noNull()
        departure.value = intent.getStringExtra(Constant.Key.DEPARTURE).noNull()
        destination.value = intent.getStringExtra(Constant.Key.DESTINATION).noNull()

        // 回填航班日期和航班号（从列表页传入）
        val passedFlightDate = intent.getStringExtra("flightDate").noNull()
        val passedFlightNo = intent.getStringExtra("flightNo").noNull()
        if (passedFlightDate.isNotEmpty()) {
            flightDate.value = passedFlightDate
        }
        if (passedFlightNo.isNotEmpty()) {
            flightNo.value = passedFlightNo
        }
        // 如果航班日期和航班号都有值且已从列表页获得航班信息，标记已查询避免重复请求
        if (passedFlightDate.isNotEmpty() && passedFlightNo.isNotEmpty() && fid.isNotEmpty()) {
            lastQueriedFlight = "$passedFlightDate-$passedFlightNo"
        }

        // 编辑模式：从Bean对象加载数据
        if (pageType.value == DetailsPageType.Modify) {
            val bean = intent.getSerializableExtra(Constant.Key.BEAN)
            if (bean is com.lukouguoji.module_base.bean.GjjManifest) {
                loadManifestFromBean(bean)
            } else if (bean is com.lukouguoji.module_base.bean.GjjImportManifest) {
                loadManifestFromImportBean(bean)
            }
        }

        // 加载下拉列表（在编辑数据加载之后，以便使用 checkedValue 将选中项置顶）
        loadDictLists()
    }

    /**
     * 加载下拉列表数据
     * 编辑模式下传入 checkedValue，handleCallBack 会将匹配项置于列表首位，
     * Spinner 默认显示首项即完成回填
     */
    private fun loadDictLists() {
        val isModify = pageType.value == DetailsPageType.Modify

        DictUtils.getIntImpAgentList(
            addAll = false,
            checkedValue = if (isModify) agent.value else null
        ) {
            agentList.postValue(if (isModify) it else listOf(KeyValue("", "")) + it)
        }

        DictUtils.getSpecialCodeList(
            addAll = false, flag = 1, ieFlag = "",
            checkedValue = if (isModify) specialCode.value else null
        ) {
            if (isModify) {
                specialCodeList.postValue(it)
            } else {
                val list = arrayListOf<KeyValue>()
                it.find { b -> b.key.contains("普通货物") }?.let { b -> list.add(b) }
                list.addAll(it.filter { b -> !b.key.contains("普通货物") })
                specialCodeList.postValue(list)
            }
        }

        DictUtils.getBusinessTypeList(
            addAll = false,
            checkedValue = if (isModify) businessType.value else null
        ) {
            businessTypeList.postValue(it)
            if (!isModify && businessType.value.isNullOrEmpty()) {
                it.find { b -> b.key.contains("普通货物运输") }?.let { b ->
                    businessType.postValue(b.value)
                }
            }
        }

        DictUtils.getShouYunPackageTypeList(
            checkedValue = if (isModify) packageType.value else null
        ) {
            packageTypeList.postValue(if (isModify) it else listOf(KeyValue("", "")) + it)
        }

        DictUtils.getWaybillTypeList(
            type = "II", addAll = false,
            checkedValue = if (isModify) waybillType.value else null
        ) {
            if (isModify) {
                waybillTypeList.postValue(it)
            } else {
                val list = arrayListOf<KeyValue>()
                it.find { b -> b.key.contains("干线") }?.let { b -> list.add(b) }
                list.addAll(it.filter { b -> !b.key.contains("干线") })
                waybillTypeList.postValue(list)
            }
        }
    }

    /**
     * 从Bean对象加载数据（编辑模式）
     */
    private fun loadManifestFromBean(manifest: com.lukouguoji.module_base.bean.GjjManifest) {
        // 保存舱单ID
        mfId = manifest.mfId
        fid = manifest.fid.toString()
        no = manifest.no
        prefix = manifest.prefix

        // 填充表单字段
        waybillNo.value = manifest.getWaybillNo()
        waybillNum.value = manifest.totalPc.toString()
        waybillWeight.value = manifest.totalWeight.toString()
        actualNum.value = manifest.pc.toString()
        actualWeight.value = manifest.weight.toString()
        billingWeight.value = manifest.cashWeight.toString()
        departure.value = manifest.origin
        destination.value = manifest.dest
        goodsNameCn.value = manifest.goodsCn
        goodsNameEn.value = manifest.goods
        unNumber.value = manifest.unNumber
        remark.value = manifest.remark

        // 设置下拉框选中值
        agent.value = manifest.agentCode
        specialCode.value = manifest.spCode
        packageType.value = manifest.packageType
        businessType.value = manifest.businessType
        goodsType.value = manifest.cargoType
        waybillType.value = manifest.awbType
    }

    /**
     * 从GjjImportManifest对象加载数据（编辑模式）
     */
    private fun loadManifestFromImportBean(manifest: com.lukouguoji.module_base.bean.GjjImportManifest) {
        fid = manifest.fid.toString()
        no = manifest.no
        prefix = manifest.prefix

        // 填充表单字段
        waybillNo.value = "${manifest.prefix}${manifest.no}"
        waybillNum.value = manifest.totalPc.toString()
        waybillWeight.value = manifest.totalWeight.toString()
        actualNum.value = manifest.pc.toString()
        actualWeight.value = manifest.weight.toString()
        departure.value = manifest.origin
        destination.value = manifest.dest
        goodsNameCn.value = manifest.goodsCn
        goodsNameEn.value = manifest.goods
        unNumber.value = manifest.unNumber
        remark.value = manifest.remark

        // 设置下拉框选中值
        agent.value = manifest.agentCode
        specialCode.value = manifest.spCode
        waybillType.value = manifest.awbType
    }

    /**
     * 校验运单号格式
     * 规则：纯数字，固定11位，后8位中前7位 mod 7 == 最后一位
     */
    private fun verifyWaybillNo(wbNo: String?): Boolean {
        if (wbNo.isNullOrEmpty()) return false
        if (wbNo.length != 11) {
            showToast("运单号必须为11位数字")
            return true
        }
        if (!wbNo.all { it.isDigit() }) {
            showToast("运单号必须为纯数字")
            return true
        }
        // 后8位：前7位 mod 7 == 最后一位
        val last8 = wbNo.substring(3) // 后8位
        val first7ofLast8 = last8.substring(0, 7).toLong()
        val lastDigit = last8.last().toString().toInt()
        if (first7ofLast8 % 7 != lastDigit.toLong()) {
            showToast("运单号校验位不正确")
            return true
        }
        return false
    }

    /**
     * 保存点击
     */
    fun onSaveClick(view: View) {
        if ((waybillNo.value.verifyNullOrEmpty("请输入运单号")
                    || verifyWaybillNo(waybillNo.value)
                    || agent.value.verifyNullOrEmpty("请选择代理")
                    || waybillNum.value.verifyNullOrEmpty("请输入运单件数")
                    || waybillWeight.value.verifyNullOrEmpty("请输入运单重量")
                    || actualNum.value.verifyNullOrEmpty("请输入实到件数")
                    || actualWeight.value.verifyNullOrEmpty("请输入实到重量")
                    || billingWeight.value.verifyNullOrEmpty("请输入计费重量")
                    || goodsNameEn.value.verifyNullOrEmpty("请输入品名(英)")
                    || waybillType.value.verifyNullOrEmpty("请选择运单类型")
                    || businessType.value.verifyNullOrEmpty("请选择业务类型")
                    || departure.value.verifyNullOrEmpty("请输入始发站")
                    || destination.value.verifyNullOrEmpty("请输入目的站")
                    )
        ) {
            return
        }

        val isModify = pageType.value == DetailsPageType.Modify

        val paramsMap = mutableMapOf<String, Any?>(
            "fid" to fid,
            "wbNo" to waybillNo.value,
            "agentCode" to agent.value,
            "spCode" to specialCode.value.let { if (it.isNullOrEmpty()) "NOR" else it },
            "businessType" to businessType.value,
            "totalPc" to waybillNum.value,
            "totalWeight" to waybillWeight.value,
            "pc" to actualNum.value,
            "weight" to actualWeight.value,
            "cashWeight" to billingWeight.value,
            "origin" to departure.value,
            "dest" to destination.value,
            "goods" to goodsNameEn.value,
            "goodsCn" to goodsNameCn.value,
            "awbType" to waybillType.value,
        )

        // 可选字段：非空时才传
        if (!packageType.value.isNullOrEmpty()) paramsMap["packageType"] = packageType.value
        if (!goodsType.value.isNullOrEmpty()) paramsMap["cargoType"] = goodsType.value
        if (!unNumber.value.isNullOrEmpty()) paramsMap["unNumber"] = unNumber.value
        if (!remark.value.isNullOrEmpty()) paramsMap["remark"] = remark.value

        // 编辑模式：必须传 mfId、no、prefix（不受空字符串过滤影响）
        if (isModify) {
            paramsMap["mfId"] = mfId
            paramsMap["no"] = no
            paramsMap["prefix"] = prefix
        }

        val params = paramsMap.toRequestBody()

        launchLoadingCollect({
            if (isModify) {
                NetApply.api.gjjManifestUpdate(params)
            } else {
                NetApply.api.gjjManifestInsert(params)
            }
        }) {
            onSuccess = {
                if (it.verifySuccess()) {
                    val successMsg = if (isModify) "修改成功" else "保存成功"
                    showToast(successMsg)

                    // 发送刷新事件
                    viewModelScope.launch {
                        FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).emit("refresh")
                    }

                    view.context.finish()
                } else {
                    showToast(it.msg.noNull("保存失败"))
                }
            }
        }
    }

    /**
     * 取消点击
     */
    fun onCancelClick(view: View) {
        view.context.finish()
    }

}