package com.hikoncont.manager

import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.BroadcastReceiver
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.Log
import com.hikoncont.MediaProjectionHolder
import com.hikoncont.service.AccessibilityRemoteService
import kotlinx.coroutines.*
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger

/**
 * 智能MediaProjection管理器
 * 
 * 专门解决Android 15投屏权限丢失问题：
 * 1. 智能区分用户主动停止和系统自动停止
 * 2. 多层级权限保持策略
 * 3. 非侵入式权限恢复机制
 * 4. 向下兼容所有Android版本
 */
class SmartMediaProjectionManager(
    private val context: Context
) {
    
    companion object {
        private const val TAG = "SmartMediaProjection"
        
        // 恢复策略配置
        private const val MAX_SILENT_RECOVERY_ATTEMPTS = 5    // 最大静默恢复次数
        private const val MAX_USER_RECOVERY_ATTEMPTS = 3      // 最大用户确认恢复次数
        private const val SILENT_RECOVERY_DELAY = 3000L       // 静默恢复延迟（3秒）
        private const val USER_RECOVERY_DELAY = 30000L        // 用户恢复延迟（30秒）
        private const val PERMISSION_CHECK_INTERVAL = 10000L  // 权限检查间隔（10秒）
        
        // Android版本特定配置
        private const val ANDROID_15_MIN_RECOVERY_INTERVAL = 120000L // Android 15最小恢复间隔（2分钟）
        
        @Volatile
        private var instance: SmartMediaProjectionManager? = null
        
        fun getInstance(context: Context): SmartMediaProjectionManager {
            return instance ?: synchronized(this) {
                instance ?: SmartMediaProjectionManager(context.applicationContext).also { instance = it }
            }
        }
    }
    
    // 状态管理
    private var mediaProjection: MediaProjection? = null
    private var mediaProjectionManager: MediaProjectionManager? = null
    private val isInitialized = AtomicBoolean(false)
    private val isRecovering = AtomicBoolean(false)
    private val silentRecoveryAttempts = AtomicInteger(0)
    private val userRecoveryAttempts = AtomicInteger(0)
    
    // 时间记录
    @Volatile private var lastPermissionLostTime = 0L
    @Volatile private var lastRecoveryTime = 0L
    @Volatile private var lastUserInteractionTime = 0L
    
    // 协程管理
    private val managerScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
    private var monitoringJob: Job? = null
    
    // 回调接口
    interface PermissionStateListener {
        fun onPermissionLost(reason: LossReason)
        fun onPermissionRecovered()
        fun onPermissionFailedToRecover()
    }
    
    enum class LossReason {
        USER_STOPPED,           // 用户主动停止
        SYSTEM_LOCK_SCREEN,     // 系统锁屏停止
        SYSTEM_AUTO_STOP,       // 系统其他原因停止
        APP_BACKGROUNDED,       // 应用后台化
        UNKNOWN                 // 未知原因
    }
    
    private val listeners = mutableSetOf<PermissionStateListener>()
    
    // 系统状态监听
    private val systemStateReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            when (intent?.action) {
                Intent.ACTION_SCREEN_OFF -> {
                    Log.i(TAG, "📱 设备锁屏，标记可能的权限丢失原因")
                    lastUserInteractionTime = System.currentTimeMillis()
                }
                Intent.ACTION_USER_PRESENT -> {
                    Log.i(TAG, "📱 用户解锁，检查权限状态")
                    checkPermissionStatusAfterUnlock()
                }
                "android.mycustrecev.USER_STOPPED_PROJECTION" -> {
                    Log.i(TAG, "👤 收到用户主动停止投屏信号")
                    handleUserStoppedProjection()
                }
            }
        }
    }
    
    /**
     * 智能MediaProjection回调
     * 
     * 🚨 核心修复：如果 Holder 中仍有有效对象，说明是旧实例被替换，
     * 不是真正的权限丢失，静默处理。
     */
    private val smartCallback = object : MediaProjection.Callback() {
        override fun onStop() {
            Log.w(TAG, "🛑 SmartManager: MediaProjection.onStop()")
            
            // 🔒 如果 Holder 正在创建新实例，旧实例的 onStop 静默跳过
            if (MediaProjectionHolder.isCreating()) {
                Log.i(TAG, "🔒 Holder正在创建新实例，旧实例onStop静默跳过")
                mediaProjection = null
                return
            }
            
            // 🛡️ Holder 中仍有有效对象，说明是旧实例被替换
            val holderProjection = MediaProjectionHolder.getMediaProjection()
            if (holderProjection != null) {
                Log.i(TAG, "🛡️ Holder中仍有有效对象，旧实例被替换，静默处理")
                mediaProjection = null
                return
            }
            
            // 权限数据仍存在，只清理本地引用，不触发恢复
            val hasPermissionData = MediaProjectionHolder.getPermissionData() != null
            if (hasPermissionData) {
                Log.i(TAG, "🛡️ 权限数据仍存在，仅清理本地引用")
                mediaProjection = null
                return
            }
            
            val currentTime = System.currentTimeMillis()
            lastPermissionLostTime = currentTime
            
            // 智能判断丢失原因
            val lossReason = determineLossReason(currentTime)
            
            // 清理当前MediaProjection引用
            cleanupCurrentProjection()
            
            // 通知监听器
            notifyPermissionLost(lossReason)
            
            // 根据丢失原因选择恢复策略
            selectRecoveryStrategy(lossReason)
        }
    }
    
    /**
     * 初始化智能管理器
     */
    fun initialize(): Boolean {
        return try {
            if (isInitialized.get()) {
                Log.d(TAG, "管理器已初始化")
                return true
            }
            
            Log.i(TAG, "🚀 初始化智能MediaProjection管理器")
            
            // 初始化MediaProjectionManager
            mediaProjectionManager = context.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as? MediaProjectionManager
            
            if (mediaProjectionManager == null) {
                Log.e(TAG, "❌ 无法获取MediaProjectionManager")
                return false
            }
            
            // 注册系统状态监听
            registerSystemStateReceiver()
            
            // 检查现有权限
            checkAndRestoreExistingPermission()
            
            // 启动权限状态监控
            startPermissionMonitoring()
            
            isInitialized.set(true)
            Log.i(TAG, "✅ 智能MediaProjection管理器初始化成功")
            
            true
        } catch (e: Exception) {
            Log.e(TAG, "❌ 初始化失败", e)
            false
        }
    }
    
    /**
     * 智能判断权限丢失原因
     */
    private fun determineLossReason(lossTime: Long): LossReason {
        return when {
            // 用户最近与状态栏交互（可能点击了停止按钮）
            lossTime - lastUserInteractionTime < 5000 -> {
                Log.i(TAG, "🤔 判断为用户主动停止（最近有用户交互）")
                LossReason.USER_STOPPED
            }
            
            // 锁屏相关的权限丢失
            lossTime - lastUserInteractionTime < 2000 -> {
                Log.i(TAG, "🔒 判断为系统锁屏自动停止")
                LossReason.SYSTEM_LOCK_SCREEN
            }
            
            // Android 15特有的系统自动停止
            Build.VERSION.SDK_INT >= 35 -> {
                Log.i(TAG, "🤖 Android 15系统自动停止")
                LossReason.SYSTEM_AUTO_STOP
            }
            
            else -> {
                Log.i(TAG, "❓ 未知原因的权限丢失")
                LossReason.UNKNOWN
            }
        }
    }
    
    /**
     * 根据丢失原因选择恢复策略
     */
    private fun selectRecoveryStrategy(reason: LossReason) {
        when (reason) {
            LossReason.USER_STOPPED -> {
                Log.i(TAG, "👤 用户主动停止，不进行自动恢复")
                // 用户主动停止，重置恢复计数器但不自动恢复
                resetRecoveryCounters()
            }
            
            LossReason.SYSTEM_LOCK_SCREEN -> {
                Log.i(TAG, "🔒 锁屏导致的权限丢失，等待解锁后恢复")
                // 等待用户解锁后再恢复
                scheduleUnlockRecovery()
            }
            
            LossReason.SYSTEM_AUTO_STOP,
            LossReason.APP_BACKGROUNDED,
            LossReason.UNKNOWN -> {
                Log.i(TAG, "🤖 系统自动停止，启动智能恢复")
                // 系统原因，启动智能恢复
                startSmartRecovery()
            }
        }
    }
    
    /**
     * 启动智能恢复机制
     */
    private fun startSmartRecovery() {
        if (isRecovering.get()) {
            Log.d(TAG, "🔄 恢复进程已在进行中")
            return
        }
        
        managerScope.launch {
            try {
                isRecovering.set(true)
                
                // 首先尝试静默恢复
                if (attemptSilentRecovery()) {
                    Log.i(TAG, "✅ 静默恢复成功")
                    return@launch
                }
                
                // 静默恢复失败，根据情况决定是否提示用户
                if (shouldPromptUserRecovery()) {
                    scheduleUserPromptedRecovery()
                } else {
                    Log.i(TAG, "🤐 不满足用户提示条件，等待下次机会")
                }
                
            } catch (e: Exception) {
                Log.e(TAG, "❌ 智能恢复失败", e)
            } finally {
                isRecovering.set(false)
            }
        }
    }
    
    /**
     * 尝试静默恢复
     * 
     * 🚨 核心修复：禁止调用 getMediaProjection() 创建新实例！
     * 每次创建新实例，系统会自动 stop 旧实例，触发 onStop 回调，
     * 形成"权限丢失→恢复→再丢失"的死循环。
     * 
     * 只从 Holder 获取已有对象，不重新创建。
     */
    private suspend fun attemptSilentRecovery(): Boolean {
        val currentAttempts = silentRecoveryAttempts.get()
        
        if (currentAttempts >= MAX_SILENT_RECOVERY_ATTEMPTS) {
            Log.w(TAG, "⚠️ 已达到最大静默恢复次数($MAX_SILENT_RECOVERY_ATTEMPTS)")
            return false
        }
        
        silentRecoveryAttempts.incrementAndGet()
        Log.i(TAG, "🤫 尝试静默恢复 (${silentRecoveryAttempts.get()}/$MAX_SILENT_RECOVERY_ATTEMPTS)")
        
        try {
            delay(SILENT_RECOVERY_DELAY)
            
            // 只从 Holder 获取已有对象
            val existingProjection = MediaProjectionHolder.getMediaProjection()
            if (existingProjection != null) {
                Log.i(TAG, "✅ Holder中已有有效MediaProjection，直接复用")
                mediaProjection = existingProjection
                notifyPermissionRecovered()
                resetRecoveryCounters()
                return true
            }
            
            // 🚨 不再重新创建！避免死循环
            Log.w(TAG, "❌ Holder中无有效MediaProjection，等待权限重新授予")
            return false
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 静默恢复异常", e)
            return false
        }
    }
    
    /**
     * 安全地创建MediaProjection
     * 🚨 核心修复：通过 MediaProjectionHolder.safeGetOrCreateProjection() 统一创建，
     * 避免重复调用 getMediaProjection() 导致旧实例被 stop 的死循环
     */
    private fun createMediaProjectionSafely(resultCode: Int, resultData: Intent): MediaProjection? {
        return try {
            val projection = MediaProjectionHolder.safeGetOrCreateProjection(
                context, resultCode, resultData
            )
            
            if (projection != null) {
                // 注册智能回调
                projection.registerCallback(smartCallback, Handler(Looper.getMainLooper()))
                
                mediaProjection = projection
                // safeGetOrCreateProjection 内部已设置到 Holder
                
                Log.i(TAG, "✅ MediaProjection创建成功（通过安全创建入口）")
            }
            
            projection
        } catch (e: Exception) {
            Log.e(TAG, "❌ 创建MediaProjection失败", e)
            null
        }
    }
    
    /**
     * 判断是否应该提示用户恢复
     */
    private fun shouldPromptUserRecovery(): Boolean {
        val currentTime = System.currentTimeMillis()
        
        // 检查用户恢复次数
        if (userRecoveryAttempts.get() >= MAX_USER_RECOVERY_ATTEMPTS) {
            Log.w(TAG, "⚠️ 已达到最大用户恢复次数")
            return false
        }
        
        // 检查最小恢复间隔（Android 15需要更长间隔）
        val minInterval = if (Build.VERSION.SDK_INT >= 35) {
            ANDROID_15_MIN_RECOVERY_INTERVAL
        } else {
            USER_RECOVERY_DELAY
        }
        
        if (currentTime - lastRecoveryTime < minInterval) {
            Log.d(TAG, "🕐 未达到最小恢复间隔")
            return false
        }
        
        // 检查是否有正在运行的AccessibilityService
        if (!AccessibilityRemoteService.isServiceRunning()) {
            Log.w(TAG, "⚠️ AccessibilityService未运行，不提示用户恢复")
            return false
        }
        
        return true
    }
    
    /**
     * 安排用户提示恢复
     */
    private fun scheduleUserPromptedRecovery() {
        managerScope.launch {
            try {
                delay(USER_RECOVERY_DELAY)
                
                userRecoveryAttempts.incrementAndGet()
                lastRecoveryTime = System.currentTimeMillis()
                
                Log.i(TAG, "🔔 启动用户提示恢复")
                
                // 发送恢复请求广播（非侵入式）
                val intent = Intent("android.mycustrecev.SMART_PERMISSION_RECOVERY").apply {
                    putExtra("recovery_type", "user_prompted")
                    putExtra("attempt", userRecoveryAttempts.get())
                    putExtra("max_attempts", MAX_USER_RECOVERY_ATTEMPTS)
                }
                context.sendBroadcast(intent)
                
            } catch (e: Exception) {
                Log.e(TAG, "❌ 用户提示恢复失败", e)
            }
        }
    }
    
    /**
     * 处理解锁后的权限检查
     */
    private fun checkPermissionStatusAfterUnlock() {
        managerScope.launch {
            try {
                delay(2000) // 等待系统稳定
                
                if (mediaProjection == null) {
                    Log.i(TAG, "🔓 解锁后检测到权限丢失，启动恢复")
                    startSmartRecovery()
                }
                
            } catch (e: Exception) {
                Log.e(TAG, "❌ 解锁后权限检查失败", e)
            }
        }
    }
    
    /**
     * 安排解锁恢复
     */
    private fun scheduleUnlockRecovery() {
        Log.i(TAG, "⏰ 安排解锁后恢复")
        // 解锁恢复会在系统状态监听器中触发
    }
    
    /**
     * 启动权限状态监控
     */
    private fun startPermissionMonitoring() {
        monitoringJob?.cancel()
        monitoringJob = managerScope.launch {
            while (isActive) {
                try {
                    delay(PERMISSION_CHECK_INTERVAL)
                    
                    // 检查MediaProjection是否仍然有效
                    val currentProjection = mediaProjection
                    if (currentProjection != null) {
                        // 执行轻量级状态检查
                        try {
                            // 这里可以添加一些检查逻辑来验证MediaProjection是否仍然有效
                            Log.v(TAG, "📊 权限状态检查：正常")
                        } catch (e: Exception) {
                            Log.w(TAG, "⚠️ 权限状态检查异常，可能已失效", e)
                            if (!isRecovering.get()) {
                                startSmartRecovery()
                            }
                        }
                    }
                    
                } catch (e: Exception) {
                    Log.e(TAG, "❌ 权限监控异常", e)
                }
            }
        }
    }
    
    /**
     * 注册系统状态监听
     */
    private fun registerSystemStateReceiver() {
        val filter = IntentFilter().apply {
            addAction(Intent.ACTION_SCREEN_OFF)
            addAction(Intent.ACTION_USER_PRESENT)
            addAction("android.mycustrecev.USER_STOPPED_PROJECTION")
        }
        context.registerReceiver(systemStateReceiver, filter)
        Log.i(TAG, "✅ 已注册系统状态监听")
    }
    
    /**
     * 检查并恢复现有权限 - 只从 Holder 获取已有对象
     */
    private fun checkAndRestoreExistingPermission() {
        try {
            // 只从 Holder 获取已有对象，不重新创建
            val existingProjection = MediaProjectionHolder.getMediaProjection()
            if (existingProjection != null) {
                Log.i(TAG, "✅ Holder中已有有效MediaProjection，直接复用")
                mediaProjection = existingProjection
                notifyPermissionRecovered()
            } else {
                Log.d(TAG, "📱 Holder中无有效MediaProjection，等待权限授予")
            }
        } catch (e: Exception) {
            Log.e(TAG, "❌ 检查现有权限失败", e)
        }
    }
    
    /**
     * 处理用户主动停止投屏
     */
    private fun handleUserStoppedProjection() {
        Log.i(TAG, "👤 处理用户主动停止投屏")
        lastUserInteractionTime = System.currentTimeMillis()
        
        // 停止所有恢复机制
        isRecovering.set(false)
        resetRecoveryCounters()
        
        // 清理MediaProjection
        cleanupCurrentProjection()
    }
    
    /**
     * 清理当前MediaProjection
     */
    private fun cleanupCurrentProjection() {
        try {
            mediaProjection?.unregisterCallback(smartCallback)
            mediaProjection = null
            
            // 🚨 重要修复：Android 15设备不要清理权限数据！
            if (android.os.Build.VERSION.SDK_INT >= 35) {
                Log.i(TAG, "🛡️ Android 15设备：仅清理MediaProjection引用，保留权限数据")
                // 不清理权限数据，避免Android 15权限丢失
            } else {
                // 其他版本可以选择性清理，但建议保留
                MediaProjectionHolder.clearMediaProjection()
                Log.i(TAG, "MediaProjection引用和权限数据已清理")
            }
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 清理MediaProjection失败", e)
        }
    }
    
    /**
     * 重置恢复计数器
     */
    private fun resetRecoveryCounters() {
        silentRecoveryAttempts.set(0)
        userRecoveryAttempts.set(0)
        Log.i(TAG, "🔄 恢复计数器已重置")
    }
    
    /**
     * 添加权限状态监听器
     */
    fun addPermissionStateListener(listener: PermissionStateListener) {
        listeners.add(listener)
    }
    
    /**
     * 移除权限状态监听器
     */
    fun removePermissionStateListener(listener: PermissionStateListener) {
        listeners.remove(listener)
    }
    
    /**
     * 通知权限丢失
     */
    private fun notifyPermissionLost(reason: LossReason) {
        listeners.forEach { listener ->
            try {
                listener.onPermissionLost(reason)
            } catch (e: Exception) {
                Log.e(TAG, "❌ 通知权限丢失失败", e)
            }
        }
    }
    
    /**
     * 通知权限恢复
     */
    private fun notifyPermissionRecovered() {
        listeners.forEach { listener ->
            try {
                listener.onPermissionRecovered()
            } catch (e: Exception) {
                Log.e(TAG, "❌ 通知权限恢复失败", e)
            }
        }
    }
    
    /**
     * 获取当前MediaProjection
     */
    fun getCurrentMediaProjection(): MediaProjection? {
        return mediaProjection
    }
    
    /**
     * 手动设置新的MediaProjection
     */
    fun setMediaProjection(resultCode: Int, resultData: Intent): Boolean {
        return try {
            val projection = createMediaProjectionSafely(resultCode, resultData)
            if (projection != null) {
                resetRecoveryCounters()
                notifyPermissionRecovered()
                true
            } else {
                false
            }
        } catch (e: Exception) {
            Log.e(TAG, "❌ 设置MediaProjection失败", e)
            false
        }
    }
    
    /**
     * 手动停止MediaProjection
     */
    fun stopMediaProjection() {
        try {
            Log.i(TAG, "🛑 用户手动停止MediaProjection")
            
            // 发送用户停止信号
            val intent = Intent("android.mycustrecev.USER_STOPPED_PROJECTION")
            context.sendBroadcast(intent)
            
            // 清理资源
            mediaProjection?.stop()
            cleanupCurrentProjection()
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 停止MediaProjection失败", e)
        }
    }
    
    /**
     * 获取管理器状态信息
     */
    fun getStatusInfo(): Map<String, Any> {
        return mapOf(
            "initialized" to isInitialized.get(),
            "hasPermission" to (mediaProjection != null),
            "isRecovering" to isRecovering.get(),
            "silentRecoveryAttempts" to silentRecoveryAttempts.get(),
            "userRecoveryAttempts" to userRecoveryAttempts.get(),
            "lastPermissionLostTime" to lastPermissionLostTime,
            "lastRecoveryTime" to lastRecoveryTime,
            "androidVersion" to Build.VERSION.SDK_INT
        )
    }
    
    /**
     * 清理资源
     */
    fun cleanup() {
        try {
            Log.i(TAG, "🧹 清理智能MediaProjection管理器")
            
            isInitialized.set(false)
            monitoringJob?.cancel()
            managerScope.cancel()
            
            cleanupCurrentProjection()
            
            context.unregisterReceiver(systemStateReceiver)
            listeners.clear()
            
            Log.i(TAG, "✅ 清理完成")
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 清理失败", e)
        }
    }
} 