package com.gh.gamecenter.core.utils

import com.gh.gamecenter.core.HaloApp
import com.gh.gamecenter.core.R
import java.text.DateFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.log10

object TimeUtils {

    /**
     * 获取今天日期
     */
    @JvmStatic
    fun getToday(): String {
        var date = Date()
        val calendar = GregorianCalendar()
        calendar.time = date
        //把日期往后增加一天.整数往后推,负数往前移动
        calendar.add(GregorianCalendar.DATE, 0)
        date = calendar.time
        val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
        return formatter.format(date)
    }

    /**
     * 获取昨天日期
     */
    @JvmStatic
    fun getYesterday(): String {
        var date = Date()
        val calendar = GregorianCalendar()
        calendar.time = date
        calendar.add(GregorianCalendar.DATE, -1)
        date = calendar.time
        val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
        return formatter.format(date)
    }

    @JvmStatic
    fun getFormatTime(time: Long, pattern: String = "yyyy-MM-dd"): String {
        val f = SimpleDateFormat(pattern, Locale.CHINA)
        f.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
        return f.format(Date(getJavaTimestamp(time)))
    }

    fun getFormatDate(timestamp: Long): String {
        val format = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
        format.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
        val testDate: String
        val today = format.parse(format.format(Date())).time
        val day = timestamp * 1000
        val timeFormat = SimpleDateFormat("HH:mm", Locale.CHINA)
        val time = timeFormat.format(day)

        testDate = if (day >= today && day < today + 86400 * 1000) {
            "今天 $time"
        } else if (day >= today + 86400 * 1000 && day < today + 86400 * 1000 * 2) {
            "明天 $time"
        } else {
            SimpleDateFormat("MM-dd HH:mm", Locale.CHINA).format(day)
        }
        return testDate
    }

    //获取当前的小时（24小时制）
    fun getCurrentHour(): Int {
        val calendar = Calendar.getInstance()
        return calendar.get(Calendar.HOUR_OF_DAY)
    }

    //判断是不是今天
    fun isToday(timestamp: Long): Boolean {
        val format = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
        format.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
        val today = format.parse(format.format(Date())).time
        val day = timestamp * 1000
        if (day >= today && day < today + 86400 * 1000) {
            return true
        }
        return false
    }

    //判断是不是明天
    fun isTomorrow(timestamp: Long): Boolean {
        val format = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
        format.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
        val today = format.parse(format.format(Date())).time
        val day = timestamp * 1000
        if (day >= today + 86400 * 1000 && day < today + 86400 * 1000 * 2) {
            return true
        }
        return false
    }

    /**
     * 判断时间戳2是不是时间戳1的第二天
     *
     * @param previousTimeMillis 时间戳1
     * @param nextTimeMillis 时间戳2
     */
    fun isNextDay(previousTimeMillis: Long, nextTimeMillis: Long): Boolean {
        val previousCalendar = Calendar.getInstance(TimeZone.getDefault())
        previousCalendar.timeInMillis = previousTimeMillis

        val nextCalendar = Calendar.getInstance(TimeZone.getDefault())
        nextCalendar.timeInMillis = nextTimeMillis

        return nextCalendar.get(Calendar.YEAR) == previousCalendar.get(Calendar.YEAR)
                && nextCalendar.get(Calendar.DAY_OF_YEAR) == previousCalendar.get(Calendar.DAY_OF_YEAR) + 1
    }


    //判断是不是本周
    fun isThisWeek(timestamp: Long): Boolean {
        val calendar = Calendar.getInstance()
        val currentWeek = calendar[Calendar.WEEK_OF_YEAR]
        calendar.time = Date(timestamp)
        val paramWeek = calendar[Calendar.WEEK_OF_YEAR]
        return paramWeek == currentWeek
    }

    /**
     * 判断时间戳是多少天前
     */
    fun getBeforeDays(timestamp: Long): Int {
        var days: Long = 0
        val format = SimpleDateFormat("yyyyMMdd HH:mm", Locale.getDefault())
        try {
            val today = format.parse(format.format(Date())).time
            val day = timestamp * 1000
            days = (today - day) / 86400000
        } catch (e: ParseException) {
            e.printStackTrace()
        }

        return days.toInt()
    }

    /**
     * 判断传入时间戳与当前日期的差值，返回单位为天
     */
    fun getDaysOffset(timestamp: Long): Int {
        var days: Long = 0
        val format = SimpleDateFormat("yyyyMMdd", Locale.getDefault())
        try {
            val today = format.parse(format.format(Date())).time
            val day = timestamp * 1000
            days = (day - today) / 86400000
        } catch (e: ParseException) {
            e.printStackTrace()
        }

        return days.toInt()
    }


    /**
     * 格式化视频时长
     */
    @JvmStatic
    fun formatVideoDuration(length: Long): String {
        val minute = length / 60
        val second = length % 60
        return String.format(Locale.CHINA, "%02d:%02d", minute, second)
    }

    /**
     * 格式化时长（将秒数转化为HH:mm:ss格式）
     */
    @JvmStatic
    fun formatDuration(seconds: Long): String {
        val hour = seconds / 3600
        val minute = seconds % 3600 / 60
        val second = seconds % 60
        return String.format(Locale.CHINA, "%02d:%02d:%02d", hour, minute, second)
    }

    @JvmStatic
    fun getDayString(date: Long): String {
        val offSet = Calendar.getInstance().timeZone.rawOffset
        val today = (System.currentTimeMillis() + offSet) / 86400000
        val start = (date * 1000 + offSet) / 86400000
        return when ((start - today).toInt()) {
            -2 -> "（前天）"
            -1 -> "（昨天）"
            0 -> "（今天）"
            1 -> "（明天）"
            2 -> "（后天）"
            else -> ""
        }
    }

    @JvmStatic
    fun getStartTimeOfToday(): Long = getStartTimeOfDay(System.currentTimeMillis())

    @JvmStatic
    fun getStartTimeOfDay(currentTime: Long): Long {
        val calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"))
        calendar.timeInMillis = getJavaTimestamp(currentTime)
        calendar.set(Calendar.HOUR_OF_DAY, 0)
        calendar.set(Calendar.MINUTE, 0)
        calendar.set(Calendar.SECOND, 0)
        calendar.set(Calendar.MILLISECOND, 0)
        return calendar.timeInMillis
    }

    @JvmStatic
    fun getTimeOfToday(hour: Int) = getTimeOfToday(hour, 0)

    @JvmStatic
    fun getTimeOfToday(hour: Int, minute: Int): Long {
        val calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"))
        calendar.timeInMillis = getJavaTimestamp(System.currentTimeMillis())
        calendar.set(Calendar.HOUR_OF_DAY, hour)
        calendar.set(Calendar.MINUTE, minute)
        calendar.set(Calendar.SECOND, 0)
        calendar.set(Calendar.MILLISECOND, 0)
        return calendar.timeInMillis
    }

    @JvmStatic
    fun getJavaTimestamp(timestamp: Long): Long {
        return if ((log10(timestamp.toDouble()) + 1).toInt() == 10) {
            timestamp * 1000
        } else {
            timestamp
        }
    }

    /**
     * 获取当前周的所有日期
     * @param n -1代表上一周 +1代表下一周
     * @param curDate 当前日期
     */
    private fun getWeekList(n: Int, curDate: Date): List<Date> {
        val date: MutableList<Date> = ArrayList()
        try {
            val calendar = Calendar.getInstance()
            calendar.firstDayOfWeek = Calendar.MONDAY
            val cal = Calendar.getInstance()
            cal.time = curDate
            //判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周了
            val dayWeek = cal[Calendar.DAY_OF_WEEK] //获得当前日期是一个星期的第几天
            if (1 == dayWeek) {
                cal.add(Calendar.DAY_OF_MONTH, -1)
            }
            //设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
            cal.firstDayOfWeek = Calendar.MONDAY
            //获得当前日期是一个星期的第几天
            val day = cal[Calendar.DAY_OF_WEEK]
            //根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
            cal.add(Calendar.DATE, cal.firstDayOfWeek - day + 7 * n)
            date.add(cal.time)
            for (i in 1..6) {
                cal.add(Calendar.DATE, 1)
                date.add(cal.time)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return date
    }

    //根据日期获得周几
    private fun getWeekString(date: Date): String {
        val weeks = arrayOf("周日", "周一", "周二", "周三", "周四", "周五", "周六")
        val cal = Calendar.getInstance()
        cal.time = date
        var weekIndex = cal[Calendar.DAY_OF_WEEK] - 1
        if (weekIndex < 0) {
            weekIndex = 0
        }
        return weeks[weekIndex]
    }

    private fun getCurrentDayOfWeek(calendar: Calendar): String {
        // 获取当前是星期几
        val dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)

        // 将 Calendar 返回的数字转换为对应的中文星期
        return when (dayOfWeek) {
            Calendar.SUNDAY -> "日"
            Calendar.MONDAY -> "一"
            Calendar.TUESDAY -> "二"
            Calendar.WEDNESDAY -> "三"
            Calendar.THURSDAY -> "四"
            Calendar.FRIDAY -> "五"
            Calendar.SATURDAY -> "六"
            else -> "日" // 理论上不会到这里
        }
    }

    /**
     * 获取当前周、上一周、下一周的日期和(上/下)周几
     * @param pattern
     */
    fun getCurrentPreviousAndNextWeek(pattern: String = "MM.dd"): ArrayList<Pair<String, String>> {
        val list: ArrayList<Pair<String, String>> = ArrayList()
        for (i in -1..1) {
            val weekList = getWeekList(i, Date())
            weekList.forEach {
                val formatTime = getFormatTime(it.time, pattern)
                val week = getWeekString(it)
                when (i) {
                    -1 -> list.add(Pair(formatTime, "上$week"))
                    1 -> list.add(Pair(formatTime, "下$week"))
                    else -> list.add(Pair(formatTime, week))
                }
            }
        }
        return list
    }

    /**
     * 获取当前周、下一周的日期和(下)周几
     * @param pattern
     */
    fun getCurrentAndNextWeek(pattern: String = "MM.dd"): ArrayList<Pair<String, String>> {
        val list: ArrayList<Pair<String, String>> = ArrayList()
        for (i in 0..1) {
            val weekList = getWeekList(i, Date())
            weekList.forEach {
                val formatTime = getFormatTime(it.time, pattern)
                val week = getWeekString(it)
                when (i) {
                    1 -> list.add(Pair(formatTime, "下$week"))
                    else -> list.add(Pair(formatTime, week))
                }
            }
        }
        return list
    }

    //获取今天昨天明天的日期
    fun getTodayYesterdayAndTomorrow(pattern: String = "MM.dd"): ArrayList<Pair<String, Int>> {
        val list: ArrayList<Pair<String, Int>> = ArrayList()
        for (i in -1..1) {
            var date = Date()
            val calendar = GregorianCalendar()
            calendar.time = date
            //把日期往后增加一天.整数往后推,负数往前移动
            calendar.add(GregorianCalendar.DATE, i)
            date = calendar.time
            val formatter = SimpleDateFormat(pattern, Locale.CHINA)
            list.add(Pair(formatter.format(date), i))
        }
        return list
    }

    /**
     * 获取新游开测转换后的时间，规则如下：
     * 时间点的分钟为“0-29分”时，直接按照0分显示；例如：10:20 显示为10:00
     * 时间点的分钟为“30-59分”时，直接按照30分显示；例如：10:50 显示为10:30
     */
    fun getGameServerTestTransformedTime(time: Long): String {
        val formatTimeHours = getFormatTime(time, "HH")
        var formatTimeMinutes = getFormatTime(time, "mm")
        val minutes = formatTimeMinutes.toInt()
        if (minutes in 1..29) {
            formatTimeMinutes = "00"
        } else if (minutes in 31..59) {
            formatTimeMinutes = "30"
        }
        return "$formatTimeHours:$formatTimeMinutes"
    }

    /**
     * 时间轴日期(yyyy-MM-dd)转时间戳
     */
    fun getDateTimeStamp(date: String): Long {
        val format: DateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
        return try {
            val d = format.parse(date) ?: return 0
            d.time
        } catch (e: Exception) {
            0
        }
    }

    /**
     *  格式化 开测时间
     *  日期：优先显示“上周X、周X、昨天、今天、明天、周X、下周X；超过“上周一/下周日”展示 XX.XX（具体月份日期）
     * 时间点：时间点的分钟为“0-29分”时，直接按照0分显示（例如：10:20 显示为10:00）；时间点的分钟为“30-59分”时，直接按照30分显示（例如：10:50 显示为10:30）
     * @param timeSeconds 单位为 秒
     */
    fun formatTestTime(timeSeconds: Long): String {

        val current = Calendar.getInstance().apply {
            timeInMillis = System.currentTimeMillis()
            firstDayOfWeek = Calendar.MONDAY
        }

        // 获取目标时间的Calendar实例
        val target = Calendar.getInstance().apply {
            timeInMillis = timeSeconds * 1000
            firstDayOfWeek = Calendar.MONDAY
        }

        val dateStr = when {
            isYesterday(current, target) -> R.string.core_yesterday.toResString()
            isSameDay(current, target) -> R.string.core_today.toResString()
            isTomorrow(current, target) -> R.string.core_tomorrow.toResString()
            isLastWeek(current, target) -> R.string.last_week_with_number.toResString(getCurrentDayOfWeek(target))
            isSameWeek(current, target) -> R.string.this_week_with_number.toResString(getCurrentDayOfWeek(target))
            isNextWeek(current,target) -> R.string.next_week_with_number.toResString(getCurrentDayOfWeek(target))
            else -> HaloApp.getInstance().resources.getString(
                R.string.date_format_month_day,
                target.get(Calendar.MONTH) + 1,
                target.get(Calendar.DAY_OF_MONTH)
            )
        }

        // 格式化时间部分
        val hour = target.get(Calendar.HOUR_OF_DAY)
        val minute = target.get(Calendar.MINUTE)
        val roundedMinute = if (minute < 30) "00" else "30"
        return HaloApp.getInstance().resources.getString(R.string.date_time_format, dateStr, hour, roundedMinute)
    }

    private fun isYesterday(current: Calendar, target: Calendar): Boolean {
        val yesterday = (current.clone() as Calendar).apply {
            add(Calendar.DAY_OF_YEAR, -1)
        }
        return isSameDay(yesterday, target)
    }

    private fun isTomorrow(current: Calendar, target: Calendar): Boolean {
        val tomorrow = (current.clone() as Calendar).apply {
            add(Calendar.DAY_OF_YEAR, 1)
        }
        return isSameDay(tomorrow, target)
    }

    private fun isSameDay(current: Calendar, target: Calendar): Boolean {
        return current.get(Calendar.YEAR) == target.get(Calendar.YEAR) &&
                current.get(Calendar.DAY_OF_YEAR) == target.get(Calendar.DAY_OF_YEAR)
    }

    private fun isLastWeek(current: Calendar, target: Calendar): Boolean {
        val lastWeek = (current.clone() as Calendar).apply {
            add(Calendar.WEEK_OF_YEAR, -1)
        }
        return isSameWeek(lastWeek, target)
    }

    private fun isNextWeek(current: Calendar, target: Calendar): Boolean {
        val nextWeek = (current.clone() as Calendar).apply {
            add(Calendar.WEEK_OF_YEAR, 1)
        }
        return isSameWeek(nextWeek, target)
    }

    private fun isSameWeek(current: Calendar, target: Calendar): Boolean {
        return current.get(Calendar.YEAR) == target.get(Calendar.YEAR) &&
                current.get(Calendar.WEEK_OF_YEAR) == target.get(Calendar.WEEK_OF_YEAR)
    }

    private fun Int.toResString(formatArg: String = "") = if (formatArg.isEmpty()) {
        HaloApp.getInstance().resources.getString(this)
    } else {
        HaloApp.getInstance().resources.getString(this, formatArg)
    }


}