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

import android.content.Context
import android.os.Parcelable
import android.util.AttributeSet
import android.util.SparseArray
import android.view.View
import android.widget.EditText
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.Spinner
import android.widget.TextView
import androidx.core.widget.doOnTextChanged
import androidx.databinding.InverseBindingListener
import com.lukouguoji.module_base.R
import com.lukouguoji.module_base.adapter.bindAdapter
import com.lukouguoji.module_base.adapter.bindOnSelected
import com.lukouguoji.module_base.interfaces.IOnSpinnerSelected
import com.lukouguoji.module_base.ktx.formatDate
import com.lukouguoji.module_base.ktx.getActivity
import com.lukouguoji.module_base.util.Common
import dev.utils.app.info.KeyValue
import java.util.Calendar

/**
 * 手机版表单 / 筛选项（5.5 寸手持端公共组件）
 *
 * 结构：上方标题（14sp #374151）+ 下方 40dp 高控件框（白底 + 1px 边框 + 8dp 圆角）。
 * 支持三种形态，由 [type] 决定：
 *
 * | type      | 控件      | 右侧图标 |
 * |-----------|-----------|----------|
 * | `INPUT`   | EditText  | 无       |
 * | `DATE`    | TextView（点击弹日历）| 日历 |
 * | `SPINNER` | Spinner   | 下箭头   |
 *
 * XML 用法：
 * ```xml
 * <com.lukouguoji.module_base.ui.weight.phone.PhoneDataLayout
 *     android:layout_width="match_parent"
 *     android:layout_height="wrap_content"
 *     title="@{`航班日期`}"
 *     hint="@{`请选择航班日期`}"
 *     type="@{PhoneDataLayoutType.DATE}"
 *     value="@={viewModel.flightDate}" />
 * ```
 *
 * 手机端专用，与平板端 PadDataLayoutNew 并列存在，互不影响。
 */
class PhoneDataLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    val tvTitle: TextView
    val tvMust: TextView
    val llContent: LinearLayout
    val et: EditText
    val tv: TextView
    val spinner: Spinner
    val iv: ImageView

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

    /** 输入完成 / 选择完成回调 */
    var refreshCallBack: (() -> Unit)? = null

    var type: PhoneDataLayoutType = PhoneDataLayoutType.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
            bindAdapter(spinner, list, v, R.layout.item_spinner_list_14sp)
        }

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

    var list: List<KeyValue> = emptyList()
        set(v) {
            field = v
            bindAdapter(spinner, v, hint, R.layout.item_spinner_list_14sp)
            applyValue()
        }

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

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

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

        tvTitle = findViewById(R.id.tv_title)
        tvMust = findViewById(R.id.tv_must)
        llContent = findViewById(R.id.ll_content)
        et = findViewById(R.id.et)
        tv = findViewById(R.id.tv)
        spinner = findViewById(R.id.spinner)
        iv = findViewById(R.id.iv)

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

        bindOnSelected(spinner, object : IOnSpinnerSelected {
            override fun onSelected(position: Int) {
                value = list.getOrNull(position)?.value ?: ""
                refreshCallBack?.invoke()
            }
        })

        applyType()
    }

    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) {
            PhoneDataLayoutType.INPUT -> {
                et.visibility = VISIBLE
                tv.visibility = GONE
                spinner.visibility = GONE
                iv.visibility = GONE
                llContent.setOnClickListener(null)
                llContent.isClickable = false
            }

            PhoneDataLayoutType.DATE -> {
                et.visibility = GONE
                tv.visibility = VISIBLE
                spinner.visibility = GONE
                iv.visibility = VISIBLE
                iv.setImageResource(R.drawable.ic_phone_calendar)
                llContent.setOnClickListener(dateClick)
            }

            PhoneDataLayoutType.SPINNER -> {
                et.visibility = GONE
                tv.visibility = GONE
                spinner.visibility = VISIBLE
                iv.visibility = VISIBLE
                iv.setImageResource(R.drawable.ic_phone_chevron_down)
                llContent.setOnClickListener(null)
                llContent.isClickable = false
            }
        }
    }

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

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

            PhoneDataLayoutType.SPINNER -> {
                if (value.isNotEmpty()) {
                    val position = list.indexOfFirst { it.value == value }
                    if (position >= 0) spinner.setSelection(position)
                }
            }
        }
    }

    /**
     * 同一页面往往放置多个本组件实例，而它们的内部子控件（et / tv / spinner）共用同一套 id。
     * 系统按 id 保存/恢复视图状态会发生跨实例串档（典型表现：日期项被邻近输入框的空文本覆盖）。
     * 这里只保存/恢复自身状态、不下发给子控件；控件取值本就由 ViewModel + DataBinding 持有，无需视图级恢复。
     */
    override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
        dispatchFreezeSelfOnly(container)
    }

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

    /** 重置为空值（筛选弹层「重置」按钮使用） */
    fun reset() {
        value = ""
        if (type == PhoneDataLayoutType.SPINNER && list.isNotEmpty()) {
            spinner.setSelection(if (hint.isEmpty()) list.size - 1 else list.size)
        }
    }
}

/** [PhoneDataLayout] 支持的控件形态 */
enum class PhoneDataLayoutType {
    INPUT,   // 文本输入
    DATE,    // 日期选择
    SPINNER, // 下拉选择
}
