package com.remax.visualnovel.ui.chat.ui.expandableSelector

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.LinearLayout
import android.widget.TextView
import com.remax.visualnovel.R
import com.remax.visualnovel.databinding.LayoutExpandSelectViewBinding
import com.remax.visualnovel.utils.spannablex.utils.dp


class ExpandSelectView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    private lateinit var mBinding: LayoutExpandSelectViewBinding

    private var isExpanded = false
    private var animationDuration = 300
    private var items: List<SelectorItem> = emptyList()
    private var itemSelectedListener: OnItemSelectedListener? = null

    init {
        initView(context, attrs)
    }

    private fun initView(context: Context, attrs: AttributeSet?) {
        mBinding = LayoutExpandSelectViewBinding.inflate(LayoutInflater.from(context), this, true)
        mBinding.itemsContainer.setBackgroundResource(R.drawable.bg_expand_view_items)
        setupAttributes(attrs)
        setupClickListeners()
    }

    private fun setupAttributes(attrs: AttributeSet?) {
        attrs?.let {
            val typedArray = context.obtainStyledAttributes(it, R.styleable.ExpandableSelector)
            val title = typedArray.getString(R.styleable.ExpandableSelector_titleText)
            title?.let { mBinding.titleText.text = it }
            animationDuration = typedArray.getInt(R.styleable.ExpandableSelector_animationDuration, 300)
            typedArray.recycle()
        }
    }

    private fun setupClickListeners() {
        mBinding.titleLayout.setOnClickListener { toggle() }
    }


    fun setTitleIcon(resId: Int) {
        mBinding.icon.setImageResource(resId)
    }

    fun setTitleText(titleRes: Int) {
        mBinding.titleText.text = context.resources.getString(titleRes)
    }

    fun setItems(newItems: List<SelectorItem>) {
        items = newItems
        updateItemsView()
    }



    private fun updateItemsView() {
        mBinding.itemsContainer.removeAllViews()

        items.forEachIndexed { index, item ->
            val itemView = createItemView(item, index)
            mBinding.itemsContainer.addView(itemView)

            if (index < items.size - 1) {
                addDivider()
            }
        }
    }

    private fun createItemView(item: SelectorItem, position: Int): View {
        val itemView = LayoutInflater.from(context)
            .inflate(R.layout.layout_item_ai_model, mBinding.itemsContainer, false)

        val colorIndicator = itemView.findViewById<View>(R.id.colorIndicator)
        val itemName = itemView.findViewById<TextView>(R.id.itemName)
        val itemDesc = itemView.findViewById<TextView>(R.id.itemDesc)
        val recommendedTag = itemView.findViewById<TextView>(R.id.recommendedTag)
        val selectedDot = itemView.findViewById<View>(R.id.selectedDot)

        (colorIndicator.background as? GradientDrawable)?.setColor(item.color)

        itemName.text = item.name
        itemDesc.text = item.description
        recommendedTag.text = item.pointsInfo
        selectedDot.visibility = if (item.isSelected) View.VISIBLE else View.GONE

        itemView.setOnClickListener {
            selectItem(position)
            itemSelectedListener?.onItemSelected(position, item)
        }

        return itemView
    }

    private fun addDivider() {
        val divider = View(context).apply {
            layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, 1.dp).apply {
                setBackgroundColor(context.resources.getColor(R.color.chat_setting_divider_color))
                marginStart = 10.dp
                marginEnd = 10.dp
            }
        }
        mBinding.itemsContainer.addView(divider)
    }


    fun selectItem(position: Int) {
        items.forEachIndexed { index, item ->
            item.isSelected = index == position
        }
        updateItemsView()

        if (position in items.indices) {
            mBinding.titleText.text = items[position].name
        }

        collapse()
    }


    fun toggle() {
        if (isExpanded) collapse() else expand()
    }

    fun expand() {
        if (isExpanded) return

        isExpanded = true
        mBinding.itemsContainer.visibility = View.VISIBLE
        animateArrow(0f, 90f)
        // param height anim
        val animator = ValueAnimator.ofInt(0, getItemsHeight())
        animator.duration = animationDuration.toLong()
        animator.interpolator = AccelerateDecelerateInterpolator()
        animator.addUpdateListener { animation ->
            val value = animation.animatedValue as Int
            val params = mBinding.itemsContainer.layoutParams
            params.height = value
            mBinding.itemsContainer.layoutParams = params
        }
        animator.start()
    }


    fun collapse() {
        if (!isExpanded) return

        isExpanded = false
        animateArrow(90f, 0f)
        // param height anim
        val animator = ValueAnimator.ofInt(getItemsHeight(), 0)
        animator.duration = animationDuration.toLong()
        animator.interpolator = AccelerateDecelerateInterpolator()
        animator.addUpdateListener { animation ->
            val value = animation.animatedValue as Int
            val params = mBinding.itemsContainer.layoutParams
            params.height = value
            mBinding.itemsContainer.layoutParams = params
        }
        animator.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                mBinding.itemsContainer.visibility = View.GONE
            }
        })
        animator.start()
    }

    private fun animateArrow(from: Float, to: Float) {
        val rotation = ObjectAnimator.ofFloat(mBinding.arrow, "rotation", from, to)
        rotation.duration = animationDuration.toLong()
        rotation.interpolator = AccelerateDecelerateInterpolator()
        rotation.start()
    }

    private fun getItemsHeight(): Int {
        var height = 0
        for (i in 0 until mBinding.itemsContainer.childCount) {
            val child = mBinding.itemsContainer.getChildAt(i)
            child.measure(
                MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
            )
            height += child.measuredHeight
        }
        return height
    }

    fun setOnItemSelectedListener(listener: OnItemSelectedListener) {
        this.itemSelectedListener = listener
    }

    interface OnItemSelectedListener {
        fun onItemSelected(position: Int, item: SelectorItem)
    }
}