package com.tomhempel.rbarometer.ui

import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.tomhempel.rbarometer.R
import com.tomhempel.rbarometer.utils.ViewUtils
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout

/**
 * Searchable bottom sheet for choosing among many assigned client codes.
 */
class ClientPickerBottomSheet(
    private val activity: AppCompatActivity,
    private val allClients: List<String>,
    private val currentClient: String?,
    private val searchHint: String,
    private val onSelected: (String) -> Unit,
) {
    private var dialog: BottomSheetDialog? = null

    fun show() {
        val sheet = BottomSheetDialog(activity)
        dialog = sheet
        val root = LayoutInflater.from(activity).inflate(R.layout.bottom_sheet_client_picker, null)
        sheet.setContentView(root)

        val searchLayout = root.findViewById<TextInputLayout>(R.id.clientSearchLayout)
        val searchInput = root.findViewById<TextInputEditText>(R.id.clientSearchInput)
        val recycler = root.findViewById<RecyclerView>(R.id.clientListRecycler)
        searchLayout.hint = searchHint

        val recent = ClientRecentStore.getRecent(activity)
            .filter { code -> allClients.any { it.equals(code, ignoreCase = true) } }
        val sortedAll = allClients.sortedBy { it.lowercase() }

        val adapter = ClientListAdapter { code ->
            sheet.dismiss()
            onSelected(code)
        }
        recycler.layoutManager = LinearLayoutManager(activity)
        recycler.adapter = adapter
        adapter.submit(buildSections(recent, sortedAll, query = ""))

        searchInput.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
            override fun afterTextChanged(s: Editable?) {
                adapter.submit(buildSections(recent, sortedAll, s?.toString().orEmpty()))
            }
        })

        sheet.show()
    }

    private fun buildSections(
        recent: List<String>,
        all: List<String>,
        query: String,
    ): List<ClientListItem> {
        val q = query.trim().lowercase()
        fun matches(code: String) = q.isBlank() || code.lowercase().contains(q)

        val items = mutableListOf<ClientListItem>()
        val recentFiltered = recent.filter { matches(it) }
        if (recentFiltered.isNotEmpty()) {
            items.add(ClientListItem.Header("__recent__"))
            recentFiltered.forEach { items.add(ClientListItem.Code(it)) }
        }
        val allFiltered = all.filter { matches(it) }
        if (allFiltered.isNotEmpty()) {
            if (items.isNotEmpty()) items.add(ClientListItem.Header("__all__"))
            allFiltered.forEach { items.add(ClientListItem.Code(it)) }
        }
        return items
    }

    private sealed class ClientListItem {
        data class Header(val tag: String) : ClientListItem()
        data class Code(val value: String) : ClientListItem()
    }

    private class ClientListAdapter(
        private val onPick: (String) -> Unit,
    ) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

        private var items: List<ClientListItem> = emptyList()

        fun submit(list: List<ClientListItem>) {
            items = list
            notifyDataSetChanged()
        }

        override fun getItemViewType(position: Int): Int = when (items[position]) {
            is ClientListItem.Header -> 0
            is ClientListItem.Code -> 1
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
            val inflater = LayoutInflater.from(parent.context)
            return if (viewType == 0) {
                val tv = TextView(parent.context).apply {
                    layoutParams = ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                    )
                    setPadding(
                        ViewUtils.dp(parent.context, 16),
                        ViewUtils.dp(parent.context, 12),
                        ViewUtils.dp(parent.context, 16),
                        ViewUtils.dp(parent.context, 4),
                    )
                    setTextColor(ContextCompat.getColor(parent.context, R.color.brand_text_muted))
                    ViewUtils.setTextSizePercentOfScreenHeight(this, 0.022f)
                }
                HeaderHolder(tv)
            } else {
                val v = inflater.inflate(R.layout.item_client_code, parent, false)
                CodeHolder(v)
            }
        }

        override fun getItemCount(): Int = items.size

        override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
            when (val item = items[position]) {
                is ClientListItem.Header -> {
                    val label = when (item.tag) {
                        "__recent__" -> holder.itemView.context.getString(R.string.client_picker_recent)
                        else -> holder.itemView.context.getString(R.string.client_picker_all)
                    }
                    (holder as HeaderHolder).text.text = label
                }
                is ClientListItem.Code -> {
                    val h = holder as CodeHolder
                    ViewUtils.setTextSizePercentOfScreenHeight(h.text, 0.028f)
                    h.text.text = item.value
                    h.itemView.setOnClickListener { onPick(item.value) }
                }
            }
        }

        private class HeaderHolder(val text: TextView) : RecyclerView.ViewHolder(text)
        private class CodeHolder(view: View) : RecyclerView.ViewHolder(view) {
            val text: TextView = view.findViewById(R.id.clientCodeText)
        }
    }
}
