package com.adealink.weparty.module.widget.form.field.multiplechoice

import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.lifecycle.LifecycleOwner
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.IError
import com.adealink.frame.base.Rlt
import com.adealink.frame.util.onClick
import com.adealink.weparty.commonui.commonSelectedDrawable
import com.adealink.weparty.commonui.ext.getActivity
import com.adealink.weparty.commonui.ext.gone
import com.adealink.weparty.commonui.ext.show
import com.adealink.weparty.databinding.WidgetMultipleChooseBinding
import com.adealink.weparty.module.widget.form.BaseWidgetView
import com.adealink.weparty.module.widget.form.IWidgetData
import com.adealink.weparty.module.widget.form.WidgetType
import com.adealink.weparty.module.widget.form.data.DoubleArrayStepField
import com.adealink.weparty.module.widget.form.data.DoubleArrayStepFieldValue
import com.adealink.weparty.module.widget.form.data.DoubleStepField
import com.adealink.weparty.module.widget.form.data.DoubleStepFieldValue
import com.adealink.weparty.module.widget.form.data.IntegerArrayStepField
import com.adealink.weparty.module.widget.form.data.IntegerArrayStepFieldValue
import com.adealink.weparty.module.widget.form.data.IntegerStepField
import com.adealink.weparty.module.widget.form.data.IntegerStepFieldValue
import com.adealink.weparty.module.widget.form.data.RequireValueNullError
import com.adealink.weparty.module.widget.form.data.StepField
import com.adealink.weparty.module.widget.form.data.StepFieldValue
import com.adealink.weparty.module.widget.form.data.StringArrayStepField
import com.adealink.weparty.module.widget.form.data.StringArrayStepFieldValue
import com.adealink.weparty.module.widget.form.data.StringStepField
import com.adealink.weparty.module.widget.form.data.StringStepFieldValue
import com.adealink.weparty.module.widget.form.dialog.MultipleChoiceDialog
import com.adealink.weparty.module.widget.form.dialog.MultipleChooseItem
import com.adealink.weparty.module.widget.form.dialog.sameWith
import com.adealink.weparty.util.formatNumberStr
import com.adealink.weparty.R as APP_R


class MultipleChoiceWidgetData(
    override val fieldData: StepField<*>
) : IWidgetData {
    override fun widgetType(): WidgetType {
        return WidgetType.MULTIPLE_CHOICE
    }
}


class MultipleChooseWidgetView(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0,
) : BaseWidgetView<MultipleChoiceWidgetData>(context, attrs, defStyle) {

    private val binding = WidgetMultipleChooseBinding.inflate(LayoutInflater.from(context), this)

    private var initItemList = listOf<MultipleChooseItem>()

    private var chooseItemList = listOf<MultipleChooseItem>()
    private var selectItemList = listOf<MultipleChooseItem>()

    init {
        binding.clContent.onClick {
            showChoice()
        }
    }

    override fun onViewCreated(lifecycleOwner: LifecycleOwner, widget: MultipleChoiceWidgetData) {
        super.onViewCreated(lifecycleOwner, widget)
        chooseItemList = widget.fieldData.constants?.map { option ->
            MultipleChooseItem(option)
        } ?: emptyList()
        if (widget.fieldData.fieldName.isEmpty()) {
            binding.tvTitle.gone()
        } else {
            binding.tvTitle.show()
            binding.tvTitle.text = widget.fieldData.fieldName
        }
        if (widget.fieldData.fieldDesc.isEmpty()) {
            binding.tvDesc.gone()
        } else {
            binding.tvDesc.show()
            binding.tvDesc.text = widget.fieldData.fieldDesc
        }
        if (widget.fieldData.example?.isValid() == true) {
            binding.btnExample.background = commonSelectedDrawable()
            binding.btnExample.show()
            binding.btnExample.onClick {
                showExampleDialog()
            }
        } else {
            binding.btnExample.gone()
        }

        val inputItems = when (widgetData?.fieldData) {
            is DoubleArrayStepField -> {
                val list = (widgetData?.fieldData as DoubleArrayStepField).fieldValue?.map {
                    formatNumberStr(it, false)
                }
                list
            }

            is DoubleStepField -> {
                val list = (widgetData?.fieldData as DoubleStepField).fieldValue?.let {
                    listOf(formatNumberStr(it, false))
                }
                list
            }

            is IntegerArrayStepField -> {
                val list = (widgetData?.fieldData as IntegerArrayStepField).fieldValue?.map {
                    formatNumberStr(it, false)
                }
                list
            }

            is IntegerStepField -> {
                val list = (widgetData?.fieldData as IntegerStepField).fieldValue?.let {
                    listOf(formatNumberStr(it, false))
                }
                list
            }

            is StringArrayStepField -> {
                val list = (widgetData?.fieldData as StringArrayStepField).fieldValue?.map {
                    it
                }
                list
            }

            is StringStepField -> {
                val list = (widgetData?.fieldData as StringStepField).fieldValue?.let {
                    listOf(it)
                }
                list
            }

            null -> {
                emptyList()
            }
        }
        initSelectList(inputItems)
    }

    private fun initSelectList(inputItems: List<String>?) {
        if (inputItems.isNullOrEmpty()) {
            this@MultipleChooseWidgetView.initItemList = emptyList()
            this@MultipleChooseWidgetView.selectItemList = emptyList()
            return
        }
        val chooseItems = mutableListOf<MultipleChooseItem>()
        for (item in chooseItemList) {
            if (inputItems.contains(item.option.key)) {
                chooseItems.add(item)
            }
        }
        this@MultipleChooseWidgetView.initItemList = chooseItems
        notifyItemsChanged(chooseItems)
    }

    private fun maxItemLimit(): Int {
        val max = widgetData?.fieldData?.validate?.arraySize?.max
        return if (max == null || max < 0) {
            Int.MAX_VALUE
        } else {
            max
        }
    }


    override fun validate(): Rlt<Any> {
        val widgetData = widgetData
        val validateData = widgetData?.fieldData?.validate
        if (widgetData == null || validateData == null) {
            return Rlt.Success(Unit)
        }
        if (validateData.required == true && selectItemList.isEmpty()) {
            return Rlt.Failed(
                RequireValueNullError(
                    getCompatString(
                        APP_R.string.common_widget_validate_require,
                        widgetData.fieldData.fieldName
                    )
                )
            )
        }
        if (validateData.arraySize != null) {
            if (validateData.arraySize.isValid()) {
                if (selectItemList.size < validateData.arraySize.min) {
                    return Rlt.Failed(
                        IError(
                            getCompatString(
                                APP_R.string.common_widget_validate_array_min,
                                widgetData.fieldData.fieldName,
                                validateData.arraySize.min.toString()
                            )
                        )
                    )
                }
                if (selectItemList.size > validateData.arraySize.max) {
                    return Rlt.Failed(
                        IError(
                            getCompatString(
                                APP_R.string.common_widget_validate_array_max,
                                widgetData.fieldData.fieldName,
                                validateData.arraySize.max.toString()
                            )
                        )
                    )
                }
            }
        }
        return Rlt.Success(Unit)
    }


    override fun getFieldValue(): StepFieldValue? {
        val widgetData = widgetData ?: return null
        val inputValue = selectItemList.map { it.option.key }
        return when (widgetData.fieldData) {
            is DoubleArrayStepField -> {
                val inputList = inputValue.mapNotNull {
                    it.toDoubleOrNull()
                }
                DoubleArrayStepFieldValue(
                    widgetData.fieldData.fieldCode,
                    inputList
                )
            }

            is DoubleStepField -> {
                val inputDouble = inputValue.firstOrNull()?.toDoubleOrNull()
                DoubleStepFieldValue(
                    widgetData.fieldData.fieldCode,
                    inputDouble
                )
            }

            is IntegerArrayStepField -> {
                val inputList = inputValue.mapNotNull {
                    it.toIntOrNull()
                }
                IntegerArrayStepFieldValue(
                    widgetData.fieldData.fieldCode,
                    inputList
                )
            }

            is IntegerStepField -> {
                val inputInteger = inputValue.firstOrNull()?.toIntOrNull()
                IntegerStepFieldValue(
                    widgetData.fieldData.fieldCode,
                    inputInteger
                )
            }

            is StringArrayStepField -> {
                StringArrayStepFieldValue(
                    widgetData.fieldData.fieldCode,
                    inputValue
                )
            }

            is StringStepField -> {
                StringStepFieldValue(
                    widgetData.fieldData.fieldCode,
                    inputValue.firstOrNull()
                )
            }
        }
    }

    override fun hasEditFieldValue(): Boolean {
        val initList = initItemList
        val currentList = selectItemList
        if (initList.size != currentList.size) {
            return true
        }
        for ((index, item) in initList.withIndex()) {
            val currentItem = currentList[index]
            if (!item.sameWith(currentItem)) {
                return true
            }
        }
        return false
    }

    private fun showChoice() {
        val widget = widgetData ?: return
        val act = context.getActivity() ?: return
        MultipleChoiceDialog().apply {
            setTitle(widget.fieldData.fieldName)
            setDesc(widget.fieldData.fieldDesc)
            setItemList(chooseItemList, selectItemList)
            setMaxLimit(maxItemLimit())
            setCallback(object : MultipleChoiceDialog.IChooseCallback {
                override fun onChoose(items: List<MultipleChooseItem>) {
                    notifyItemsChanged(items)
                }
            })
        }.show(act.supportFragmentManager)
    }

    private fun notifyItemsChanged(items: List<MultipleChooseItem>) {
        val nextItems = items.take(maxItemLimit())
        selectItemList = nextItems
        binding.tvContent.text = nextItems.joinToString(separator = ",") { it.getDisplayName() }
    }
}