package com.remax.notification.check

import com.remax.notification.config.NotificationConfigController
import com.remax.notification.utils.NotiLogger
import com.remax.notification.utils.ResetAtMidnightController
import com.blankj.utilcode.util.TimeUtils
import com.remax.base.ext.canSendNotification
import com.remax.base.report.DataReportManager
import com.remax.notification.NotifyConst
import com.remax.notification.timing.NotificationTimingController

/**
 * 通知检查控制器
 * 统一处理通知前的各种检查逻辑
 */
class NotificationCheckController private constructor() {

    companion object {
        private const val TAG = "NotificationCheckController"
        
        @Volatile
        private var INSTANCE: NotificationCheckController? = null
        
        fun getInstance(): NotificationCheckController {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: NotificationCheckController().also { INSTANCE = it }
            }
        }
    }

    // 使用0点重置控制器管理通知时间和计数
    private val resetController = ResetAtMidnightController.getInstance()
    
    // 通知时间相关的键名常量
    private object Keys {
        const val LAST_UNLOCK_NOTIFICATION_TIME = "last_unlock_notification_time"
        const val LAST_BACKGROUND_NOTIFICATION_TIME = "last_background_notification_time"
        const val CURRENT_NOTIFICATION_COUNT = "current_notification_count"
    }

    // 通知计数相关
    private var context: android.content.Context? = null
    private var cachedInstallTime: Long = 0L

    /**
     * 通知类型枚举
     */
    enum class NotificationType(val string: String) {
        UNLOCK("local_push"),      // 解锁通知
        BACKGROUND("local_push"),  // app后台 - for withdraw
        FIXTIMEPOINT("fix_time_point_push"), // 每日固定时间点 "9:10""12:10""13:10""19:10""21:00""22:30""23:30"
        APPINSTALL("app_install"),
        CHARGE("charge"),
        KEEPALIVE("local_push"),   // 保活通知（无间隔限制）
        FCM("firebase_push"),          // FCM 推送通知（无间隔限制）
        RESIDENT("top_notification")          // 常驻（无间隔限制）
    }

    /**
     * 初始化通知检查控制器
     * @param context 上下文
     */
    fun initialize(context: android.content.Context) {
        if (this.context != null) {
            NotiLogger.d("通知检查控制器已经初始化")
            return
        }

        this.context = context.applicationContext
        resetController.initialize(context)
        NotiLogger.d("通知检查控制器初始化完成")
    }

    /**
     * 检查是否可以触发指定类型的通知，并返回拦截原因
     * @param type 通知类型
     * @return 检查结果，包含是否可以触发和拦截原因
     */
    fun canTriggerNotificationWithReason(type: NotificationType): Pair<Boolean, NotificationBlockReason?> {
        // 1. 检查基础条件（通知权限、开关、免打扰、前台状态、总次数限制、新用户冷却时间）
        val basicConditionResult = checkAllConditionsWithReason()
        if (!basicConditionResult.first) {
            return Pair(false, basicConditionResult.second)
        }

        // 2. 检查触发间隔
        val intervalResult = checkTriggerIntervalWithReason(type)
        if (!intervalResult.first) {
            return Pair(false, intervalResult.second)
        }

        return Pair(true, null)
    }

    /**
     * 检查所有触发条件，并返回拦截原因
     * @return 检查结果，包含是否满足所有条件和拦截原因
     */
    private fun checkAllConditionsWithReason(): Pair<Boolean, NotificationBlockReason?> {

        // 检查通知次数限制
        val totalCount = NotificationConfigController.getTotalPushCount()
        val currentCount = getCurrentNotificationCount()
        if (currentCount >= totalCount) {
            NotiLogger.d("已达到通知次数限制: $currentCount/$totalCount")
            return Pair(false, NotificationBlockReason.DAILY_LIMIT_REACHED)
        }

        // 检查通知权限
        if (!canSendNotification()) {
            NotiLogger.d("无通知权限")
            return Pair(false, NotificationBlockReason.NO_PERMISSION)
        }

        // 检查通知开关
        if (!NotificationConfigController.isNotificationEnabled()) {
            NotiLogger.d("通知开关已关闭")
            return Pair(false, NotificationBlockReason.NOTIFICATION_DISABLED)
        }

        // 检查免打扰时间段
        if (NotificationConfigController.isInDoNotDisturbTime()) {
            val startTime = NotificationConfigController.getDoNotDisturbStartTime()
            val endTime = NotificationConfigController.getDoNotDisturbEndTime()
            NotiLogger.d("当前在免打扰时间段内 (${startTime}-${endTime})")
            return Pair(false, NotificationBlockReason.DO_NOT_DISTURB)
        }

        // 检查应用前台状态
        if (NotificationTimingController.getInstance().isAppInForeground()) {
            NotiLogger.d("通知检查未通过：应用在前台，不发送通知")
            return Pair(false, NotificationBlockReason.APP_IN_FOREGROUND)
        }

        // 检查新用户冷却时间
        val cooldownMinutes = NotificationConfigController.getNewUserCooldownMin()
        if (cooldownMinutes > 0) {
            val currentTime = System.currentTimeMillis()
            val cooldownMs = cooldownMinutes * 60 * 1000L
            val appInstallTime = getAppInstallTime()
            
            if (currentTime - appInstallTime < cooldownMs) {
                val remainingMinutes = ((cooldownMs - (currentTime - appInstallTime)) / (60 * 1000)).toInt()
                NotiLogger.d("新用户冷却时间未满足，还需等待 ${remainingMinutes} 分钟 (冷却时长: ${cooldownMinutes} 分钟)")
                return Pair(false, NotificationBlockReason.NEW_USER_COOLDOWN)
            }
        }

        return Pair(true, null)
    }

    /**
     * 检查是否有通知权限
     * @return 是否有通知权限
     */
    private fun canSendNotification(): Boolean {
        val context = context ?: return false
        
        return try {
            context.canSendNotification()
        } catch (e: Exception) {
            NotiLogger.e("检查通知权限失败", e)
            false
        }
    }

    /**
     * 检查触发间隔，并返回拦截原因
     * @param type 通知类型
     * @return 检查结果，包含是否满足触发间隔要求和拦截原因
     */
    private fun checkTriggerIntervalWithReason(type: NotificationType): Pair<Boolean, NotificationBlockReason?> {
        val currentTime = System.currentTimeMillis()
        val lastTime = getLastNotificationTimeInternal(type)
        val intervalMs = getNotificationInterval(type)

        // 如果是第一次触发，或者距离上次触发已经超过间隔时间
        val canTrigger = lastTime == 0L || (currentTime - lastTime) >= intervalMs
        
        if (!canTrigger) {
            val remainingMinutes = ((lastTime + intervalMs - currentTime) / (60 * 1000)).toInt()
            val intervalMinutes = (intervalMs / (60 * 1000)).toInt()
            NotiLogger.d("${type.name}通知间隔未满足，还需等待 ${remainingMinutes} 分钟 (间隔时长: ${intervalMinutes} 分钟)")
            return Pair(false, NotificationBlockReason.TRIGGER_INTERVAL_NOT_MET)
        }

        return Pair(true, null)
    }

    /**
     * 获取应用安装时间（通过包信息获取，带缓存）
     * @return 应用安装时间戳
     */
    private fun getAppInstallTime(): Long {
        // 如果已经缓存了安装时间，直接返回
        if (cachedInstallTime > 0) {
            return cachedInstallTime
        }

        return try {
            val packageInfo = context?.packageManager?.getPackageInfo(
                context?.packageName ?: "",
                0
            )
            
            // firstInstallTime 是应用首次安装的时间（Android P+）
            val installTime = if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
                packageInfo?.firstInstallTime ?: System.currentTimeMillis()
            } else {
                // Android P 以下版本使用 lastUpdateTime 作为近似值
                packageInfo?.lastUpdateTime ?: System.currentTimeMillis()
            }
            
            // 缓存安装时间
            cachedInstallTime = installTime
            
            NotiLogger.d("应用安装时间: ${TimeUtils.millis2String(installTime)}")
            installTime
        } catch (e: Exception) {
            NotiLogger.e("获取应用安装时间失败", e)
            // 如果获取失败，返回24小时前的时间（表示已经过了冷却期）
            val fallbackTime = System.currentTimeMillis() - (24 * 60 * 60 * 1000L)
            cachedInstallTime = fallbackTime
            fallbackTime
        }
    }

    /**
     * 获取指定类型通知的最后触发时间（内部使用）
     * @param type 通知类型
     * @return 最后触发时间
     */
    private fun getLastNotificationTimeInternal(type: NotificationType): Long {
        return when (type) {
            NotificationType.UNLOCK -> resetController.getLongValue(Keys.LAST_UNLOCK_NOTIFICATION_TIME)
            NotificationType.BACKGROUND -> resetController.getLongValue(Keys.LAST_BACKGROUND_NOTIFICATION_TIME)
            else -> 0L
        }
    }

    /**
     * 获取指定类型通知的间隔时间（毫秒）
     * @param type 通知类型
     * @return 间隔时间（毫秒）
     */
    private fun getNotificationInterval(type: NotificationType): Long {
        return when (type) {
            NotificationType.UNLOCK -> NotificationConfigController.getUnlockPushIntervalMin() * NotifyConst.MIN_INTERVAL_UNIT
            NotificationType.BACKGROUND -> NotificationConfigController.getBackgroundPushIntervalMin() * NotifyConst.MIN_INTERVAL_UNIT
            else -> 0L
        }
    }

    /**
     * 记录通知触发时间
     * @param type 通知类型
     */
    fun recordNotificationTrigger(type: NotificationType) {
        val currentTime = System.currentTimeMillis()
        when (type) {
            NotificationType.UNLOCK -> resetController.setLongValue(Keys.LAST_UNLOCK_NOTIFICATION_TIME, currentTime)
            NotificationType.BACKGROUND -> resetController.setLongValue(Keys.LAST_BACKGROUND_NOTIFICATION_TIME, currentTime)
            else -> {
                // 其它，因为无间隔限制
                NotiLogger.d("${type.name}通知触发，不记录时间")
            }
        }
        NotiLogger.d("${type.name}通知触发时间: ${TimeUtils.millis2String(currentTime, "yyyy-MM-dd HH:mm:ss")}")
    }

    /**
     * 获取当前通知次数（不进行0点重置）
     * @return 当前通知次数
     */
    private fun getCurrentNotificationCount(): Int {
        return resetController.getIntValue(Keys.CURRENT_NOTIFICATION_COUNT, enableMidnightReset = false)
    }

    /**
     * 增加通知计数（外部调用）
     */
    fun incrementNotificationCount() {
        val newCount = resetController.incrementIntValue(Keys.CURRENT_NOTIFICATION_COUNT, enableMidnightReset = false)
        NotiLogger.d("通知计数增加: $newCount")
    }

    /**
     * 重置所有通知时间记录
     */
    fun resetAllNotificationTimes() {
        resetController.resetValue(Keys.LAST_UNLOCK_NOTIFICATION_TIME)
        resetController.resetValue(Keys.LAST_BACKGROUND_NOTIFICATION_TIME)
        NotiLogger.d("重置所有通知时间记录")
    }

    /**
     * 重置指定类型的通知时间记录
     * @param type 通知类型
     */
    fun resetNotificationTime(type: NotificationType) {
        when (type) {
            NotificationType.UNLOCK -> resetController.resetValue(Keys.LAST_UNLOCK_NOTIFICATION_TIME)
            NotificationType.BACKGROUND -> resetController.resetValue(Keys.LAST_BACKGROUND_NOTIFICATION_TIME)
            else -> {
                // 其它，无需重置
                NotiLogger.d("${type.name}通知无时间记录，无需重置")
            }
        }
        NotiLogger.d("重置${type.name}通知时间记录")
    }

    /**
     * 获取指定类型通知的最后触发时间（外部接口）
     * @param type 通知类型
     * @return 最后触发时间
     */
    fun getLastNotificationTime(type: NotificationType): Long {
        return getLastNotificationTimeInternal(type)
    }

    /**
     * 获取指定类型通知的剩余等待时间（分钟）
     * @param type 通知类型
     * @return 剩余等待时间（分钟）
     */
    fun getRemainingWaitTime(type: NotificationType): Int {
        val currentTime = System.currentTimeMillis()
        val lastTime = getLastNotificationTimeInternal(type)
        val intervalMs = getNotificationInterval(type)

        if (lastTime == 0L) return 0

        val remainingMs = lastTime + intervalMs - currentTime
        return if (remainingMs > 0) (remainingMs / (60 * 1000)).toInt() else 0
    }

        /**
     * 重置今日通知计数
     */
    fun resetTodayNotificationCount() {
        resetController.resetValue(Keys.CURRENT_NOTIFICATION_COUNT, enableMidnightReset = false)
        NotiLogger.d("重置通知计数")
    }

    /**
     * 获取今日通知计数
     * @return 今日已发送的通知数量
     */
    fun getTodayNotificationCount(): Int {
        return resetController.getIntValue(Keys.CURRENT_NOTIFICATION_COUNT, enableMidnightReset = false)
    }

    /**
     * 获取剩余可发送通知数量
     * @return 剩余可发送数量
     */
    fun getRemainingNotificationCount(): Int {
        val totalCount = NotificationConfigController.getTotalPushCount()
        val currentCount = getTodayNotificationCount()
        return maxOf(0, totalCount - currentCount)
    }

    /**
     * 检查是否还有剩余通知次数
     * @return 是否还有剩余次数
     */
    fun hasRemainingNotificationCount(): Boolean {
        return getRemainingNotificationCount() > 0
    }

    /**
     * 获取通知统计信息
     * @return 通知统计信息字符串
     */
    fun getNotificationStats(): String {
        val totalCount = NotificationConfigController.getTotalPushCount()
        val currentCount = getTodayNotificationCount()
        val remainingCount = getRemainingNotificationCount()
        val installTime = getAppInstallTime()
        val installDate = java.time.Instant.ofEpochMilli(installTime)
        
        return "今日已发送: $currentCount, 总限制: $totalCount, 剩余: $remainingCount, 安装时间: $installDate"
    }
}
