package com.adealink.weparty.commonui.widget.wheel

import android.os.Bundle
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.mvvm.view.viewBinding
import com.adealink.frame.util.timeToYMD
import com.adealink.weparty.R
import com.adealink.weparty.commonui.BaseFragment
import com.adealink.weparty.commonui.MIN_YEAR
import com.adealink.weparty.databinding.FragmentWheelDatePickerBinding
import java.util.Calendar
import java.util.Date
import kotlin.math.max

/**
 * 日期选择控件；
 */
class WheelDatePickerFragment : BaseFragment(R.layout.fragment_wheel_date_picker) {

    companion object {
        const val EXTRA_INIT_DATE = "extra_init_date"
        const val EXTRA_CURRENT_DATE = "extra_current_date"

        fun newInstance(
            selectTimestamp: Long = System.currentTimeMillis(),
            currentTimestamp: Long = System.currentTimeMillis()
        ): WheelDatePickerFragment {
            val fragment = WheelDatePickerFragment()
            val bundle = Bundle()
            bundle.putLong(EXTRA_INIT_DATE, selectTimestamp)
            bundle.putLong(EXTRA_CURRENT_DATE, currentTimestamp)
            fragment.arguments = bundle
            return fragment
        }
    }

    private val binding by viewBinding(FragmentWheelDatePickerBinding::bind)

    private val yearList = mutableListOf<String>()
    private val monthList =
        mutableListOf<Pair<Int, String>>()  //first用于索引及获取相应时间戳，second用于日期控件滚轮文案显示
    private val dayList = mutableListOf<String>()
    private var initTimestamp = System.currentTimeMillis()
    private var currentTimestamp = System.currentTimeMillis()

    private var minYear = MIN_YEAR

    private var selectYear = 0
    private var selectMonth = 0
    private var selectDay = 0

    private var currYear = 0
    private var currMonth = 1
    private var currDay = 1

    private fun parseIntent() {
        arguments?.getLong(EXTRA_INIT_DATE)?.let {
            initTimestamp = it
        }
        if (initTimestamp <= 0) {
            initTimestamp = System.currentTimeMillis()
        }
        arguments?.getLong(EXTRA_CURRENT_DATE)?.let {
            currentTimestamp = it
        }
        if (currentTimestamp <= 0) {
            currentTimestamp = System.currentTimeMillis()
        }
    }

    /**
     * - get(Calendar.MONTH) 比真实的月份少1；
     */
    private fun initDataPicker() {
        val cal = Calendar.getInstance()
        cal.clear()
        cal.setTime(Date(currentTimestamp))
        currYear = cal.get(Calendar.YEAR)
        currMonth = cal.get(Calendar.MONTH) + 1
        currDay = cal.get(Calendar.DAY_OF_MONTH)
        val currTimestamp = cal.timeInMillis
        //防越界
        if (currTimestamp < initTimestamp) {
            initTimestamp = currTimestamp
        }
        // 初始化选中的时间
        val date = Date(initTimestamp)
        cal.time = date
        selectYear = cal.get(Calendar.YEAR)
        selectMonth = cal.get(Calendar.MONTH) + 1
        selectDay = cal.get(Calendar.DAY_OF_MONTH)
        // 填充列表
        for (year in minYear..currYear) {
            yearList.add("$year")
        }
    }

    private fun inflateMonthList(month: Int) {
        when (month) {
            1 -> monthList.add(Pair(1, getCompatString(R.string.commonui_january)))
            2 -> monthList.add(Pair(2, getCompatString(R.string.commonui_february)))
            3 -> monthList.add(Pair(3, getCompatString(R.string.commonui_march)))
            4 -> monthList.add(Pair(4, getCompatString(R.string.commonui_april)))
            5 -> monthList.add(Pair(5, getCompatString(R.string.commonui_may)))
            6 -> monthList.add(Pair(6, getCompatString(R.string.commonui_june)))
            7 -> monthList.add(Pair(7, getCompatString(R.string.commonui_july)))
            8 -> monthList.add(Pair(8, getCompatString(R.string.commonui_august)))
            9 -> monthList.add(Pair(9, getCompatString(R.string.commonui_september)))
            10 -> monthList.add(Pair(10, getCompatString(R.string.commonui_october)))
            11 -> monthList.add(Pair(11, getCompatString(R.string.commonui_november)))
            else -> monthList.add(Pair(12, getCompatString(R.string.commonui_december)))
        }
    }

    override fun initViews() {
        parseIntent()
        initDataPicker()
        binding.wheelYear.setEntries(yearList)
        updateMonthList()

        // 设置选中x
        binding.wheelYear.currentIndex = selectYear - minYear
        binding.wheelMonth.currentIndex = monthList.indexOfFirst { it.first == selectMonth }
        binding.wheelDay.currentIndex = dayList.indexOf(selectDay.toString())
        binding.wheelYear.setOnWheelChangedListener { _, _, newIndex ->
            selectYear = yearList.getOrNull(newIndex)?.toInt() ?: 0
            updateMonthList()
            updateDayList()
        }
        binding.wheelMonth.setOnWheelChangedListener { _, _, newIndex ->
            selectMonth = monthList.getOrNull(newIndex)?.first ?: 0
            updateDayList()
        }
        binding.wheelDay.setOnWheelChangedListener { _, _, newIndex ->
            selectDay = dayList.getOrNull(newIndex)?.toInt() ?: 0
        }
    }

    fun getSelectedDate(callback: (timestamp: Long, timeStr: String) -> Unit) {
        val calendar = Calendar.getInstance()
        calendar.clear()
        calendar.set(selectYear, selectMonth - 1, selectDay)
        val timestamp = calendar.timeInMillis
        callback.invoke(
            timestamp,
            timeToYMD(timestamp)
        )
    }


    /**
     * 更新可选择的月份；
     * 1. 只有1年：直接从小到大填充月份；注意目标月份是否大于当前月份
     * 2. 跨年：[targetMonth, 12] 、[1, currMonth]
     */
    private fun updateMonthList() {
        monthList.clear()
        val endMonth = if (selectYear == currYear) {
            currMonth
        } else {
            12
        }

        for (month in 1..endMonth) {
            inflateMonthList(month)
        }
        binding.wheelMonth.setEntries(
            monthList.map { it.second },
            selectMonth.coerceIn(1, endMonth) - 1
        )
        updateDayList()
    }

    /**
     * 更新可选择的日子；
     */
    private fun updateDayList() {
        val calendar = Calendar.getInstance()
        calendar[Calendar.YEAR] = selectYear
        calendar[Calendar.MONTH] = selectMonth - 1
        val days = calendar.getActualMaximum(Calendar.DAY_OF_MONTH)
        dayList.clear()
        val endDay = if (selectYear == currYear && selectMonth == currMonth) {
            currDay
        } else {
            days
        }
        for (i in 1..endDay) {
            dayList.add("$i")
        }

        binding.wheelDay.setEntries(dayList, selectDay.coerceIn(1, endDay) - 1)
    }


    interface ISelectDateCallback {
        /**
         * @param timeStr "yyyy-MM-dd" 格式 或者“yyyy-MM-DD-HH-MM-SS”
         */
        fun onSelectComplete(timestamp: Long, timeStr: String)
    }
}