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

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.IError
import com.adealink.frame.base.Rlt
import com.adealink.frame.base.fastLazy
import com.adealink.frame.coroutine.dispatcher.Dispatcher
import com.adealink.frame.mvvm.lifecycle.viewScope
import com.adealink.frame.oss.data.UploadFile
import com.adealink.frame.util.onClick
import com.adealink.weparty.commonui.commonSelectedDrawable
import com.adealink.weparty.commonui.ext.dp
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.commonui.mediapicker.imageselect.comp.TakeFromAlbumComp
import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
import com.adealink.weparty.commonui.recycleview.diffutil.BaseListDiffUtil
import com.adealink.weparty.commonui.recycleview.itemdecoration.HorizontalItemDecoration
import com.adealink.weparty.databinding.WidgetSinglePictureBinding
import com.adealink.weparty.image.PHOTO_WALL_IMAGE_MAX_HEIGHT
import com.adealink.weparty.image.PHOTO_WALL_IMAGE_MAX_SIZE_KB
import com.adealink.weparty.image.PHOTO_WALL_IMAGE_MAX_WIDTH
import com.adealink.weparty.image.PHOTO_WALL_IMAGE_MIN_QUALITY
import com.adealink.weparty.module.image.data.PhotoData
import com.adealink.weparty.module.image.data.sameWith
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.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.UnSupportFieldDataException
import com.adealink.weparty.module.widget.form.field.picture.adapter.AddPictureItemViewBinder
import com.adealink.weparty.module.widget.form.field.picture.adapter.PictureItemViewBinder
import com.adealink.weparty.util.goImagePreviewActivity
import com.adealink.weparty.util.uploadPhotos
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.adealink.weparty.R as APP_R


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

}

@SuppressLint("SetTextI18n")
class PictureWidgetView(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0,
) : BaseWidgetView<PictureWidgetData>(context, attrs, defStyle) {

    companion object {
        private const val MAX_PICTURE_LIMIT = 9 //最多9张图
    }

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

    private var initPictureList = listOf<PhotoData>()

    private val pictureAdapter by fastLazy { MultiTypeListAdapter<BasePictureItemData>(BaseListDiffUtil()) }

    private val pictureList = mutableListOf<PhotoData>()
    private lateinit var takeFromAlbumComp: TakeFromAlbumComp

    override fun checkWidgetValid(widget: PictureWidgetData) {
        if ((widget.fieldData !is StringArrayStepField)) {
            throw UnSupportFieldDataException(
                getCompatString(
                    APP_R.string.common_widget_config_error,
                    widget.fieldData.fieldName,
                    getCompatString(APP_R.string.common_widget_value_type_string_array)
                )
            )
        }
    }

    override fun onViewCreated(lifecycleOwner: LifecycleOwner, widget: PictureWidgetData) {
        super.onViewCreated(lifecycleOwner, widget)
        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()
        }

        //图片
        TakeFromAlbumComp(
            lifecycleOwner,
            clipParamData = null,
            onSelect = { path, uri ->
                addPicture(path, uri)
            },
            source = "TakeFromAlbum_${widget.fieldData.fieldCode}"
        ).also {
            takeFromAlbumComp = it
        }.attach()

        pictureAdapter.register(
            AddPictureItemViewBinder {
                addPicture()
            }
        )
        pictureAdapter.register(
            PictureItemViewBinder(
                onItemClick = {
                    previewPicture(it.data)
                },
                onDeleteClick = {
                    deletePicture(it.data)
                }
            ))
        binding.rvPicture.adapter = pictureAdapter
        binding.rvPicture.layoutManager =
            LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
        binding.rvPicture.addItemDecoration(
            HorizontalItemDecoration(10.dp(), 0, 0)
        )

        initPictureList = ((widgetData?.fieldData as? StringArrayStepField)?.fieldValue?.map {
            PhotoData(url = it, path = null, uri = null)
        } ?: emptyList()).take(maxPictureLimit())

        pictureList.clear()
        pictureList.addAll(initPictureList)
        onPictureListChanged()
    }

    private fun maxPictureLimit(): Int {
        return widgetData?.fieldData?.validate?.arraySize?.max ?: MAX_PICTURE_LIMIT
    }

    private fun addPicture() {
        takeFromAlbumComp.takeFromAlbum()
    }

    private fun previewPicture(data: PhotoData) {
        val act = context.getActivity() ?: return
        val uri = data.url ?: data.uri
        if (uri.isNullOrEmpty()) {
            return
        }
        goImagePreviewActivity(
            act,
            arrayListOf(uri)
        )
    }

    private fun deletePicture(data: PhotoData) {
        removePicture(data)
    }


    fun addPicture(path: String?, uri: String?) {
        viewScope.launch {
            pictureList.add(0, PhotoData(null, path, uri))
            onPictureListChanged()
        }
    }

    fun removePicture(data: PhotoData) {
        viewScope.launch {
            pictureList.remove(data)
            onPictureListChanged()
        }
    }

    private fun onPictureListChanged() {
        val itemList = mutableListOf<BasePictureItemData>()
        itemList.addAll(
            pictureList.map {
                PictureItemData(it)
            }
        )
        if (pictureList.size < maxPictureLimit()) {
            itemList.add(0, AddPictureItemData)
        }
        pictureAdapter.submitList(itemList)
    }

    override fun validate(): Rlt<Any> {
        val validateData = widgetData?.fieldData?.validate
        if (validateData == null) {
            return Rlt.Success(Unit)
        }
        if (validateData.required == true) {
            if (pictureList.isEmpty()) {
                return Rlt.Failed(
                    IError(
                        getCompatString(
                            APP_R.string.common_widget_picture_validate_require_fail,
                            widgetData?.fieldData?.fieldName ?: ""
                        )
                    )
                )
            }
        }
        if (validateData.arraySize != null) {
            if (validateData.arraySize.isValid()) {
                if (pictureList.size < validateData.arraySize.min) {
                    return Rlt.Failed(
                        IError(
                            getCompatString(
                                APP_R.string.common_widget_picture_validate_min_error,
                                widgetData?.fieldData?.fieldName ?: "",
                                validateData.arraySize.min.toString()
                            )
                        )
                    )
                }
                if (pictureList.size > validateData.arraySize.max) {
                    return Rlt.Failed(
                        IError(
                            getCompatString(
                                APP_R.string.common_widget_picture_validate_max_error,
                                widgetData?.fieldData?.fieldName ?: "",
                                validateData.arraySize.max.toString()
                            )
                        )
                    )
                }
            }
        }
        return Rlt.Success(Unit)
    }

    override suspend fun beforeSubmit(): Rlt<Any> {
        return withContext(Dispatcher.WENEXT_THREAD_POOL) {
            val validateRlt = validate()
            if (validateRlt is Rlt.Failed) {
                return@withContext Rlt.Success(Unit)
            }
            val loadPictureList = pictureList.filter { !it.isRemote() }
            return@withContext uploadPhotos(
                loadPictureList,
                PHOTO_WALL_IMAGE_MAX_WIDTH,
                PHOTO_WALL_IMAGE_MAX_HEIGHT,
                PHOTO_WALL_IMAGE_MAX_SIZE_KB,
                PHOTO_WALL_IMAGE_MIN_QUALITY,
                UploadFile.FileType.IMAGE
            )
        }
    }

    override fun getFieldValue(): StepFieldValue? {
        val widgetData = widgetData ?: return null
        val pictureUrls = pictureList.mapNotNull { it.url }
        return StringArrayStepFieldValue(
            widgetData.fieldData.fieldCode,
            pictureUrls
        )
    }

    override fun hasEditFieldValue(): Boolean {
        val initList = initPictureList
        val currentList = pictureList
        if (initList.size != currentList.size) {
            return true
        }
        for ((index, data) in initList.withIndex()) {
            val currentData = currentList[index]
            if (!data.sameWith(currentData)) {
                return true
            }
        }
        return false
    }
}