package com.lukouguoji.module_base.ui.weight.phone

import android.content.Context
import android.os.Parcelable
import android.text.InputType
import android.util.AttributeSet
import android.util.SparseArray
import android.view.Gravity
import android.view.View
import android.widget.EditText
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.widget.doOnTextChanged
import androidx.databinding.InverseBindingListener
import com.lukouguoji.module_base.R
import com.lukouguoji.module_base.ktx.formatDate
import com.lukouguoji.module_base.ktx.getActivity
import com.lukouguoji.module_base.util.Common
import com.lxj.xpopup.XPopup
import dev.utils.app.info.KeyValue
import java.util.Calendar

/**
 * 手机版行式表单项（5.5 寸手持端公共组件）
 *
 * 结构：左标签（固定 110dp，+ 必填星）+ 右值区 + 可选箭头 + 底部 1px 分隔线。
 * 对应设计稿中新增 / 修改 / 详情三态共用的行式表单（如 01_ULD管理）。
 * 与 [PhoneDataLayout]（上下结构，用于筛选弹层）互补，形态见 [PhoneFormRowType]。
 *
 * XML 用法（type 按页面状态用三元切换即可覆盖三态页面）：
 * ```xml
 * <com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
 *     android:layout_width="match_parent"
 *     android:layout_height="wrap_content"
 *     title='@{"所属航司"}'
 *     hint='@{"请选择所属航司"}'
 *     list="@{viewModel.carrierList}"
 *     type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.SELECT}"
 *     value="@={viewModel.uldBean.carrier}" />
 * ```
 */
class PhoneFormRow @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    val tvTitle: TextView
    val tvMust: TextView
    val et: EditText
    val tv: TextView
    val ivArrow: ImageView
    val llRow: LinearLayout

    /** 双向绑定回调 */
    var onChangeListener: InverseBindingListener? = null

    /** 选择 / 日期确定后的回调 */
    var refreshCallBack: (() -> Unit)? = null

    var type: PhoneFormRowType = PhoneFormRowType.INPUT
        set(v) {
            field = v
            applyType()
            applyValue()
        }

    var title: String = ""
        set(v) {
            field = v
            tvTitle.text = v
        }

    var hint: String = ""
        set(v) {
            field = v
            et.hint = v
            tv.hint = v
        }

    var value: String = ""
        set(v) {
            if (field == v) return
            field = v
            applyValue()
            onChangeListener?.onChange()
        }

    /** SELECT 形态的选项（key 显示文案 / value 业务值） */
    var list: List<KeyValue> = emptyList()
        set(v) {
            field = v
            applyValue()
        }

    var required: Boolean = false
        set(v) {
            field = v
            tvMust.visibility = if (v) VISIBLE else GONE
        }

    var enable: Boolean = true
        set(v) {
            field = v
            et.isEnabled = v
            applyType()
        }

    /** INPUT 形态是否数字键盘（自重等数值项） */
    var numeric: Boolean = false
        set(v) {
            field = v
            et.inputType = if (v) {
                InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
            } else {
                InputType.TYPE_CLASS_TEXT
            }
        }

    init {
        orientation = VERTICAL
        inflate(context, R.layout.layout_phone_form_row, this)

        llRow = findViewById(R.id.ll_row)
        tvTitle = findViewById(R.id.tv_title)
        tvMust = findViewById(R.id.tv_must)
        et = findViewById(R.id.et)
        tv = findViewById(R.id.tv)
        ivArrow = findViewById(R.id.iv_arrow)

        et.doOnTextChanged { text, _, _, _ ->
            // 仅 INPUT 形态才回写，避免隐藏的 EditText 被系统状态恢复时误清空值
            if (type == PhoneFormRowType.INPUT) {
                value = text.toString()
            }
        }

        applyType()
    }

    private val selectClick: (v: View) -> Unit = {
        if (enable && list.isNotEmpty()) {
            XPopup.Builder(context)
                .asBottomList(hint.ifEmpty { title }, list.map { it.key }.toTypedArray()) { position, _ ->
                    value = list.getOrNull(position)?.value ?: ""
                    refreshCallBack?.invoke()
                }
                .show()
        }
    }

    private val dateClick: (v: View) -> Unit = {
        if (enable) {
            Common.onYearMonthDay(context.getActivity(), value) { year, month, day ->
                val calendar = Calendar.getInstance()
                calendar.set(year, month - 1, day)
                value = calendar.time.formatDate()
                refreshCallBack?.invoke()
            }
        }
    }

    private fun applyType() {
        when (type) {
            PhoneFormRowType.INPUT -> {
                et.visibility = VISIBLE
                tv.visibility = GONE
                ivArrow.visibility = GONE
                llRow.setOnClickListener(null)
                llRow.isClickable = false
            }

            PhoneFormRowType.SELECT -> {
                et.visibility = GONE
                tv.visibility = VISIBLE
                tv.gravity = Gravity.START or Gravity.CENTER_VERTICAL
                ivArrow.visibility = if (enable) VISIBLE else GONE
                llRow.setOnClickListener(selectClick)
            }

            PhoneFormRowType.DATE -> {
                et.visibility = GONE
                tv.visibility = VISIBLE
                tv.gravity = Gravity.START or Gravity.CENTER_VERTICAL
                ivArrow.visibility = GONE
                llRow.setOnClickListener(dateClick)
            }

            PhoneFormRowType.TEXT -> {
                et.visibility = GONE
                tv.visibility = VISIBLE
                tv.gravity = Gravity.END or Gravity.CENTER_VERTICAL
                tv.hint = ""
                ivArrow.visibility = GONE
                llRow.setOnClickListener(null)
                llRow.isClickable = false
            }
        }
    }

    private fun applyValue() {
        when (type) {
            PhoneFormRowType.INPUT -> {
                if (et.text.toString() != value) et.setText(value)
            }

            PhoneFormRowType.SELECT -> {
                // 显示选中项的文案；列表里找不到就按原值显示（如后端返回的历史值）
                tv.text = list.firstOrNull { it.value == value }?.key ?: value
            }

            PhoneFormRowType.DATE -> {
                tv.text = value
            }

            PhoneFormRowType.TEXT -> {
                // 只读展示：空值统一占位 "--"（与设计稿一致）
                tv.text = value.ifEmpty { "--" }
            }
        }
    }

    /** 只保存/恢复自身状态，避免内部子控件 id 与其他实例串档（公共组件必做，见 components.md） */
    override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
        dispatchFreezeSelfOnly(container)
    }

    override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) {
        dispatchThawSelfOnly(container)
    }
}
