package com.narutohuo.xindazhou

import android.app.Application
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import com.alibaba.android.arouter.launcher.ARouter
import com.narutohuo.xindazhou.common.config.ServerConfigManager
import com.narutohuo.xindazhou.share.factory.ShareServiceFactory
import com.narutohuo.xindazhou.socketio.factory.SocketIORepositoryFactory
import com.narutohuo.xindazhou.user.datasource.local.TokenManager
import com.narutohuo.xindazhou.user.repository.AuthRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

/**
 * 应用程序入口
 */
class XinDaZhouApplication : Application(), LifecycleObserver {
    
    // 用于后台执行 SocketIO 重连的协程作用域
    private val appScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
    
    override fun onCreate() {
        super.onCreate()
        
        // 初始化 ARouter（必须在其他初始化之前）
        if (BuildConfig.DEBUG) {
            // 开启日志
            ARouter.openLog()
            // 开启调试模式（如果在InstantRun模式下运行，必须开启调试模式！线上版本需要关闭,否则有安全风险)
            ARouter.openDebug()
        }
        // 初始化 ARouter
        ARouter.init(this)
        
        // 初始化 ServerConfigManager
        ServerConfigManager.init(applicationContext)
        
        // 初始化 TokenManager
        TokenManager.init(applicationContext)
        
        // 初始化网络管理器（使用 Fastjson）
        val isDebug = try {
            BuildConfig.DEBUG
        } catch (e: Exception) {
            false
        }
        com.narutohuo.xindazhou.core.network.NetworkManager.init(
            com.narutohuo.xindazhou.core.network.NetworkConfig.Builder()
                .baseUrl(ServerConfigManager.getHttpServerUrl())
                .isDebug(isDebug)
                .enableLogging(isDebug)
                .build()
        )
        
        // 配置 NetworkManager 的 Token 提供器
        com.narutohuo.xindazhou.core.network.NetworkManager.tokenProvider = {
            TokenManager.getAccessToken()
        }
        
        // 初始化分享服务（从资源文件读取配置）
        // 注意：需要在 strings.xml 中配置 share_umeng_app_key 等参数
        try {
            ShareServiceFactory.init(applicationContext)
            android.util.Log.d("XinDaZhouApplication", "分享服务初始化成功")
        } catch (e: Exception) {
            // 分享服务初始化失败不影响应用运行，但分享功能将不可用
            android.util.Log.e("XinDaZhouApplication", "分享服务初始化失败", e)
        }
        
        // 注册 App 生命周期监听（监听前后台切换）
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    }
    
    /**
     * App 进入前台时调用
     * 
     * 检查 SocketIO 连接状态，如果断开则自动重连
     * 如果连接失败（可能是 Token 过期），会自动刷新 Token 后重连
     */
    @OnLifecycleEvent(androidx.lifecycle.Lifecycle.Event.ON_START)
    fun onAppForeground() {
        android.util.Log.d("XinDaZhouApplication", "App 进入前台，检查 SocketIO 连接状态")
        
        // 检查是否已登录
        if (!TokenManager.isLoggedIn()) {
            android.util.Log.d("XinDaZhouApplication", "用户未登录，跳过 SocketIO 重连")
            return
        }
        
        // 检查连接状态，如果断开则重连
        appScope.launch {
            val socketIORepository = SocketIORepositoryFactory.getInstance()
            val socketUrl = ServerConfigManager.getSocketIOUrl()
            var token = TokenManager.getAccessToken()
            
            if (token.isNullOrEmpty()) {
                android.util.Log.w("XinDaZhouApplication", "Token 为空，无法重连 SocketIO")
                return@launch
            }
            
            // 如果已连接，无需重连
            if (socketIORepository.isConnected()) {
                android.util.Log.d("XinDaZhouApplication", "SocketIO 已连接，无需重连")
                return@launch
            }
            
            // 先尝试连接
            android.util.Log.d("XinDaZhouApplication", "SocketIO 未连接，开始重连...")
            socketIORepository.checkAndReconnect(socketUrl, token)
            
            // 等待 2 秒，检查连接是否成功
            delay(2000)
            
            // 如果连接仍然失败，可能是 Token 过期，尝试刷新 Token 后重连
            if (!socketIORepository.isConnected()) {
                android.util.Log.d("XinDaZhouApplication", "连接失败，可能是 Token 过期，尝试刷新 Token 后重连")
                val refreshedToken = refreshTokenIfNeeded()
                if (!refreshedToken.isNullOrEmpty() && refreshedToken != token) {
                    android.util.Log.d("XinDaZhouApplication", "Token 已刷新，使用新 Token 重连")
                    socketIORepository.checkAndReconnect(socketUrl, refreshedToken)
                } else {
                    android.util.Log.w("XinDaZhouApplication", "Token 刷新失败或未刷新，无法重连")
                }
            } else {
                android.util.Log.d("XinDaZhouApplication", "SocketIO 重连成功")
            }
        }
    }
    
    /**
     * 刷新 Token（如果需要）
     * 
     * @return 新的 accessToken，如果刷新失败返回 null
     */
    private suspend fun refreshTokenIfNeeded(): String? {
        val refreshToken = TokenManager.getRefreshToken()
        if (refreshToken.isNullOrEmpty()) {
            android.util.Log.w("XinDaZhouApplication", "RefreshToken 为空，无法刷新")
            return null
        }
        
        return try {
            val authRepository = AuthRepository()
            val result = authRepository.refreshToken(refreshToken)
            
            result.getOrNull()?.let { loginResponse ->
                // 保存新的 Token
                TokenManager.saveToken(
                    loginResponse.accessToken,
                    loginResponse.refreshToken,
                    loginResponse.userId
                )
                android.util.Log.d("XinDaZhouApplication", "Token 刷新成功")
                loginResponse.accessToken
            } ?: run {
                android.util.Log.w("XinDaZhouApplication", "Token 刷新失败: ${result.exceptionOrNull()?.message}")
                null
            }
        } catch (e: Exception) {
            android.util.Log.e("XinDaZhouApplication", "Token 刷新异常", e)
            null
        }
    }
    
    /**
     * App 进入后台时调用
     * 
     * 注意：通常不断开 SocketIO 连接，因为：
     * 1. SocketIO 连接是轻量级的
     * 2. 用户可能需要在后台接收消息
     * 3. 系统会在内存不足时自动清理
     */
    @OnLifecycleEvent(androidx.lifecycle.Lifecycle.Event.ON_STOP)
    fun onAppBackground() {
        android.util.Log.d("XinDaZhouApplication", "App 进入后台")
        // 不断开连接，保持连接以便接收消息
    }
}

