package com.lukouguoji.gjj.viewModel

import android.content.Intent
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import androidx.recyclerview.widget.RecyclerView
import com.lukouguoji.gjj.R
import com.lukouguoji.module_base.base.BaseViewModel
import com.lukouguoji.module_base.bean.FileBean
import com.lukouguoji.module_base.bean.GjAccidentVisaEditBean
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.impl.ImageSelectNewViewHolder
import com.lukouguoji.module_base.interfaces.IOnItemClickListener
import com.lukouguoji.module_base.ktx.commonAdapter
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 okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import com.lukouguoji.module_base.ktx.verifyNullOrEmpty
import com.lukouguoji.module_base.util.MediaUtil
import com.lukouguoji.module_base.util.UploadUtil
import dev.utils.app.info.KeyValue
import dev.utils.common.DateUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch

class IntImpAccidentVisaEditViewModel : BaseViewModel(), IOnItemClickListener {

    var id: Long = 0

    val pageType = MutableLiveData(DetailsPageType.Add)

    val dataBean = MutableLiveData(GjAccidentVisaEditBean())

    // 图片列表
    val itemLayoutId = R.layout.item_image_select_new
    val itemViewHolder = ImageSelectNewViewHolder::class.java
    var rv: RecyclerView? = null

    // 下拉列表
    val outerPackageList = MutableLiveData<List<KeyValue>>(emptyList())
    val damageTypeList = MutableLiveData<List<KeyValue>>(emptyList())
    val contentTypeList = MutableLiveData<List<KeyValue>>(emptyList())
    val unusualTypeList = MutableLiveData<List<KeyValue>>(emptyList())
    val photoList = MutableLiveData(
        listOf(KeyValue("是", "是"), KeyValue("否", "否"))
    )

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

    ///////////////////////////////////////////////////////////////////////////
    // 初始化
    ///////////////////////////////////////////////////////////////////////////

    // 是否为详情模式（只读）
    val isDetailMode = MutableLiveData(false)
    // 详情模式下无图片时显示占位提示
    val showNoImage = MutableLiveData(false)

    fun initOnCreate(intent: Intent) {
        id = intent.getLongExtra(Constant.Key.ID, 0)
        val isDetail = intent.getBooleanExtra("is_detail", false)

        pageType.value = when {
            isDetail && id != 0L -> DetailsPageType.Details
            id == 0L -> DetailsPageType.Add
            else -> DetailsPageType.Modify
        }
        isDetailMode.value = pageType.value == DetailsPageType.Details

        // 新增模式下默认航班日期为今天
        if (pageType.value == DetailsPageType.Add) {
            val bean = dataBean.value ?: GjAccidentVisaEditBean()
            bean.fdate = DateUtils.getCurrentTime().formatDate()
            dataBean.value = bean
        }

        loadDropdownLists()

        if (id != 0L) {
            loadDetail()
        }

        // 详情模式不添加空白占位图片
        if (!isDetail) {
            rv?.post {
                rv?.commonAdapter()?.addItem(FileBean())
            }
        }
    }

    private fun loadDropdownLists() {
        launchCollect({ NetApply.api.getPackTypeList() }) {
            onSuccess = { result ->
                outerPackageList.value = result.data?.mapNotNull { bean ->
                    bean.name?.let { name -> KeyValue(name, name) }
                } ?: emptyList()
            }
        }
        launchCollect({ NetApply.api.getDamageTypeList() }) {
            onSuccess = { result ->
                damageTypeList.value = result.data?.mapNotNull { bean ->
                    bean.name?.let { name -> KeyValue(name, name) }
                } ?: emptyList()
            }
        }
        launchCollect({ NetApply.api.getContentTypeList() }) {
            onSuccess = { result ->
                contentTypeList.value = result.data?.mapNotNull { bean ->
                    bean.name?.let { name -> KeyValue(name, name) }
                } ?: emptyList()
            }
        }
        launchCollect({ NetApply.api.getUnusualTypeList() }) {
            onSuccess = { result ->
                unusualTypeList.value = result.data?.mapNotNull { bean ->
                    bean.name?.let { name -> KeyValue(name, name) }
                } ?: emptyList()
            }
        }
    }

    private fun loadDetail() {
        launchLoadingCollect({ NetApply.api.getGjAccidentVisaDetail(id) }) {
            onSuccess = {
                dataBean.value = it.data ?: GjAccidentVisaEditBean()

                // 渲染图片：path 取原图 URL 确保预览清晰，url 取缩略图用于提交
                val bean = dataBean.value!!
                val picList = bean.pic.split(",").filter { it.isNotEmpty() }
                val originalList = bean.originalPic.split(",").filter { it.isNotEmpty() }
                val images = picList.mapIndexed { index, picUrl ->
                    val originalUrl = originalList.getOrElse(index) { picUrl }
                    FileBean(
                        path = MediaUtil.fillUrl(originalUrl),
                        url = picUrl,
                        originalPic = originalUrl
                    )
                }
                rv?.commonAdapter()?.loadMore(images)

                // 详情模式下无图片时显示占位提示
                if (isDetailMode.value == true && picList.isEmpty()) {
                    showNoImage.value = true
                }
            }
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // 航班级联查询
    ///////////////////////////////////////////////////////////////////////////

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

    fun onFlightNoInputComplete() {
        lastQueriedFlight = ""
        clearFlightInfo()
        queryFlightIfReady()
    }

    private fun clearFlightInfo() {
        val b = dataBean.value ?: GjAccidentVisaEditBean()
        b.dep = ""
        b.dest = ""
        dataBean.value = b
    }

    private fun queryFlightIfReady() {
        val bean = dataBean.value ?: return
        val fdate = bean.fdate
        val fno = bean.fno
        if (fdate.isEmpty() || fno.isEmpty()) 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!!
                    val b = dataBean.value ?: GjAccidentVisaEditBean()
                    b.dep = flight.fdep.noNull()
                    b.dest = flight.fdest.noNull()
                    dataBean.value = b
                } else {
                    val b = dataBean.value ?: GjAccidentVisaEditBean()
                    b.dep = ""
                    b.dest = ""
                    dataBean.value = b
                    showToast(it.msg.noNull("获取航班信息失败"))
                }
            }

            onFailed = { _, _ ->
                val b = dataBean.value ?: GjAccidentVisaEditBean()
                b.dep = ""
                b.dest = ""
                dataBean.value = b
            }
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // 保存
    ///////////////////////////////////////////////////////////////////////////

    /**
     * 校验运单号格式
     * 规则：纯数字，固定11位，后8位中前7位 mod 7 == 最后一位
     * 返回 true 表示校验失败（有错误）
     */
    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
        }
        val last8 = wbNo.substring(3)
        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() {
        val bean = dataBean.value ?: return
        if (bean.fdate.verifyNullOrEmpty("请输入航班日期")) return
        if (bean.fno.verifyNullOrEmpty("请输入航班号")) return
        if (bean.wbNo.verifyNullOrEmpty("请输入运单号")) return
        if (verifyWaybillNo(bean.wbNo)) return
        if (bean.dep.verifyNullOrEmpty("请先填写航班信息（始发站不能为空）")) return
        if (bean.dest.verifyNullOrEmpty("请先填写航班信息（目的站不能为空）")) return

        (rv?.commonAdapter()?.items ?: emptyList())
            .asFlow()
            .map { it as FileBean }
            .filter { it.path.isNotEmpty() && it.url.isEmpty() }
            .onEach {
                val data = UploadUtil.upload(it.path).data
                // UploadUtil 返回：newName=原图(较大)，zipFileName=缩略图(较小)
                // FileBean.url 用作缩略图标识，FileBean.originalPic 用作原图标识
                it.url = data?.zipFileName ?: ""
                it.originalPic = data?.newName ?: ""
            }
            .flowOn(Dispatchers.IO)
            .onStart { showLoading() }
            .catch {
                showToast(it.message.noNull("上传图片失败"))
                dismissLoading()
            }
            .onCompletion {
                launchLoadingCollect({
                    val list = (rv?.commonAdapter()?.items as List<FileBean>)
                        .filter { it.path.isNotEmpty() }
                    bean.picNumber = list.size.toString()
                    bean.pic = list.joinToString(separator = ",") { MediaUtil.removeUrl(it.url) }
                    bean.originalPic = list.joinToString(separator = ",") { MediaUtil.removeUrl(it.originalPic) }
                    bean.idFlag = "1"

                    if (pageType.value == DetailsPageType.Add) {
                        val jsonObj = org.json.JSONObject(NetApply.gson.toJson(bean))
                        jsonObj.remove("id")
                        val body = jsonObj.toString().toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
                        NetApply.api.saveGjAccidentVisa(body)
                    } else {
                        NetApply.api.modifyGjAccidentVisa(bean.toRequestBody())
                    }
                }) {
                    onSuccess = {
                        showToast(it.msg.noNull("${pageType.value!!.title}成功"))
                        viewModelScope.launch {
                            FlowBus.with<String>(ConstantEvent.EVENT_REFRESH).emit("refresh")
                        }
                        getTopActivity().finish()
                    }
                }
            }
            .launchIn(viewModelScope)
    }

    fun onCancelClick() {
        getTopActivity().finish()
    }

    ///////////////////////////////////////////////////////////////////////////
    // 图片操作
    ///////////////////////////////////////////////////////////////////////////

    override fun onItemClick(position: Int, type: Int) {
        // 详情模式下不允许长按删除操作
        if (isDetailMode.value == true) return

        val adapter = rv!!.commonAdapter()!!
        val bean = adapter.getItem(position) as FileBean
        when (type) {
            R.id.rl -> {
                bean.canDelete.set(!bean.canDelete.get())
            }

            R.id.iv_delete -> {
                adapter.removeItem(position)
            }

            else -> {}
        }
    }
}
